package com.xz.sales.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.apply.service.IPurchaseApplyService;
import com.xz.common.annotation.DataScope;
import com.xz.common.core.domain.AjaxResult;
import com.xz.common.core.domain.entity.SysDept;
import com.xz.common.core.domain.entity.SysUser;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.xz.common.utils.RedisCode;
import com.xz.common.utils.SecurityUtils;
import com.xz.common.utils.StringUtils;
import com.xz.diagnosis.vo.SalesPurchaseApplyVo;
import com.xz.expense.domain.ExpenseBill;
import com.xz.expense.mapper.ExpenseBillMapper;
import com.xz.member.domain.GiftReceive;
import com.xz.member.domain.MemberInfo;
import com.xz.member.mapper.GiftReceiveMapper;
import com.xz.member.mapper.MemberInfoMapper;
import com.xz.member.mapper.WalletRecordMapper;
import com.xz.member.service.IIntegralRecordService;
import com.xz.member.service.IWalletRecordService;
import com.xz.message.service.ISysTenantNotifyItemService;
import com.xz.message.vo.MemberMsgInfo;
import com.xz.optometry.service.IOptometryService;
import com.xz.optometry.vo.OptometryInfoVo;
import com.xz.patient.domain.PatientInfo;
import com.xz.patient.mapper.PatientInfoMapper;
import com.xz.process.domain.ProcessOrder;
import com.xz.process.domain.ProcessOrderItem;
import com.xz.process.mapper.ProcessOrderMapper;
import com.xz.process.service.IProcessOrderService;
import com.xz.product.domain.Product;
import com.xz.product.domain.ProductMeasuringUnit;
import com.xz.product.mapper.ProductMapper;
import com.xz.product.service.IProductMeasuringUnitService;
import com.xz.purchase.domain.PurchaseProduct;
import com.xz.purchase.mapper.PurchaseProductMapper;
import com.xz.repertory.domain.RepertoryFlow;
import com.xz.repertory.service.IRepertoryFlowService;
import com.xz.sales.domain.*;
import com.xz.sales.enums.EditTypeEnum;
import com.xz.sales.mapper.*;
import com.xz.sales.param.SalesOrderParam;
import com.xz.sales.service.ISalesOrderService;
import com.xz.sales.util.ProcessOrderUtil;
import com.xz.sales.util.SalesExcelUtils;
import com.xz.sales.vo.*;
import com.xz.system.service.ISysDeptService;
import com.xz.warehouse.dto.WarehouseDto;
import com.xz.warehouse.mapper.WarehouseMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 销售单信息Service业务层处理
 *
 * @author xz
 * @date 2024-01-31
 */
@Service
public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOrder> implements ISalesOrderService {
	@Autowired
	private SalesOrderMapper salesOrderMapper;
	@Autowired
	private SalesOrderDetailMapper salesOrderDetailMapper;
	@Resource
	private WarehouseMapper warehouseMapper;
	@Resource
	private SalesOriginalOrderDetailMapper originalOrderDetailMapper;
	@Resource
	private WalletRecordMapper walletRecordMapper;
	@Resource
	private ProductMapper productMapper;
	@Resource
	private MemberInfoMapper memberInfoMapper;
	@Autowired
	private ISysTenantNotifyItemService sysTenantNotifyItemService;
	@Autowired
	private ISysDeptService sysDeptService;
	@Resource
	private PatientInfoMapper patientInfoMapper;
	@Autowired
	private IProcessOrderService processOrderService;
	@Autowired
	private IOptometryService optometryService;
	@Resource
	private PurchaseProductMapper purchaseProductMapper;
	@Autowired
	private IRepertoryFlowService iRepertoryFlowService;
	@Resource
	private SalesRuleSettingMapper salesRuleSettingMapper;
	@Resource
	private GiftReceiveMapper giftReceiveMapper;
	@Resource
	private ExpenseBillMapper expenseBillMapper;
	@Resource
	private SalesReturnMapper salesReturnMapper;
	@Autowired
	private IWalletRecordService walletRecordService;
	@Autowired
	private IIntegralRecordService integralRecordService;
	@Resource
	private SalesPurchaseMapper salesPurchaseMapper;
	@Resource
	private SalesReturnDetailMapper salesReturnDetailMapper;
	@Resource
	private SalesExchangeDetailMapper salesExchangeDetailMapper;
	@Resource
	private ProcessOrderMapper processOrderMapper;
	@Autowired
	private IPurchaseApplyService purchaseApplyService;
	@Autowired
	private IProductMeasuringUnitService iProductMeasuringUnitService;

	/**
	 * 查询销售单信息
	 *
	 * @param salesNo 销售单号
	 * @return 销售单信息
	 */
	@Override
	public SalesOrder selectSalesOrderByNo(String salesNo) {
		LambdaQueryWrapper<SalesOrder> wrapper = Wrappers.lambdaQuery(SalesOrder.class);
		wrapper.eq(SalesOrder::getSalesNo, salesNo);
		List<SalesOrder> list = salesOrderMapper.selectList(wrapper);
		return CollectionUtils.isEmpty(list) ? null : list.get(0);
	}

	/**
	 * 查询销售单信息
	 *
	 * @param id 销售单信息主键
	 * @return 销售单信息
	 */
	@Override
	public SalesOrderVo selectSalesOrderById(Long id) {

		SalesOrderVo vo = new SalesOrderVo();
		SalesOrder salesOrder = salesOrderMapper.selectSalesOrderById(id);
		BeanUtils.copyProperties(salesOrder, vo);
		//
		SysDept sysDept = sysDeptService.selectDeptById(salesOrder.getDeptId());
		vo.setSalesDeptName(sysDept.getDeptName());
		if (Objects.nonNull(salesOrder.getCollaborateDeptId())) {
			SysDept sysDept1 = sysDeptService.selectDeptById(salesOrder.getCollaborateDeptId());
			vo.setCollaborateDeptName(sysDept1.getDeptName());
		}

		ProcessOrder processOrder = processOrderMapper.queryBySalesOrderId(id);
		if (Objects.nonNull(processOrder)) {
			vo.setTrackingNumber(processOrder.getTrackingNumber());

		}

		PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
		vo.setPatientName(patientInfo.getPatientName());
		vo.setPhoneNumber(patientInfo.getPhoneNumber());
		vo.setSex(patientInfo.getSex());
		vo.setBirthday(patientInfo.getBirthday());
		OptometryInfoVo optometryInfoVo = optometryService.selectProcessOptometryById(salesOrder.getOptometryId());
		vo.setOptometryInfoVo(optometryInfoVo);
		List<SalesOriginalOrderDetail> salesOrderDetails = originalOrderDetailMapper.selectBySalesId(id);
		for (SalesOriginalOrderDetail detail : salesOrderDetails) {
			if (StringUtils.isNotEmpty(detail.getUseReceiveGift())) {
				String useReceiveGift = detail.getUseReceiveGift();
				List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
				detail.setUseGiftReceiveList(giftReceives);
			}
		}
		vo.setDetailList(salesOrderDetails);
		List<SalesOrderDetail> deliverDetailList = salesOrderDetailMapper.selectBySalesId(id);
		for (SalesOrderDetail detail : deliverDetailList) {
			Product product = productMapper.selectById(detail.getProductId());
			if (null != product) {
				detail.setSeries(product.getSeries());
				detail.setSpecification(product.getSpecification());
				detail.setManufacturer(product.getManufacturer());
				detail.setRegistrationNo(product.getRegistrationNo());
				ProductMeasuringUnit unit = iProductMeasuringUnitService.getById(product.getProdNameId());
				detail.setProdName(null == unit ? null : unit.getName());
			}

			SalesPurchase salesPurchase = new SalesPurchase();
			salesPurchase.setSalesId(detail.getSalesId());
			salesPurchase.setDetailId(detail.getId());
			List<PurchaseProduct> purchaseProduct =  salesPurchaseMapper.selectPurchaseList(salesPurchase);
			if(!CollectionUtils.isEmpty(purchaseProduct)){
				detail.setBatchDate(purchaseProduct.get(0).getBatchDate());
			}

			if (StringUtils.isNotEmpty(detail.getUseReceiveGift())) {
				String useReceiveGift = detail.getUseReceiveGift();
				List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
				detail.setUseGiftReceiveList(giftReceives);
			}
			if (Objects.nonNull(detail.getDeliveryDeptId())) {
				SysDept sysDept1 = sysDeptService.selectDeptById(detail.getDeliveryDeptId());
				detail.setDeliveryDeptName(sysDept1.getDeptName());
			}
			if (detail.getDetailType().equals(2)) {
				SalesReturnDetail salesReturnDetail = salesReturnDetailMapper.selectByNewDetailId(detail.getId());
				if (Objects.nonNull(salesReturnDetail)) {
					detail.setReturnWarehouseName(salesReturnDetail.getWarehouseName());
				}
			}
			if (detail.getDetailType().equals(0)) {
				SalesExchangeDetail exchangeDetail = salesExchangeDetailMapper.selectOldReturnDetail(detail.getId());
				if (Objects.nonNull(exchangeDetail)) {
					detail.setReturnWarehouseName(exchangeDetail.getDetailReturnWarehouseName());
				}
			}
			// 找出最后交付的时间
			final Date detailDeliveryTime = detail.getDeliveryTime();
			if (null != detailDeliveryTime) {
				final Date voDeliveryTime = vo.getDeliveryTime();
				if (null == voDeliveryTime || voDeliveryTime.getTime() < detailDeliveryTime.getTime()) {
					vo.setDeliveryTime(detailDeliveryTime);
				}
			}
		}

		BigDecimal walletBalance = new BigDecimal("0.00");
		if (StringUtils.isNotEmpty(salesOrder.getMemberCardNo())) {
			MemberInfo memberInfo = memberInfoMapper.memberInfoByCardNo(salesOrder.getMemberCardNo());
			walletBalance = walletBalance.add(memberInfo.getWalletBalance());
		}
		vo.setWalletBalance(walletBalance);

		// 查询 可退金额
		BigDecimal zeroAmount = new BigDecimal("0.00");
		BigDecimal walletPay = salesOrder.getWalletPay() == null ? zeroAmount : salesOrder.getWalletPay();
		BigDecimal pendingAmount = salesOrder.getPendingAmount() == null ? zeroAmount : salesOrder.getPendingAmount();


		SalesReturn salesReturn = new SalesReturn();
		salesReturn.setSalesOrderId(salesOrder.getId());
		salesReturn.setReturnStatus(4);
		List<SalesReturn> salesReturns = salesReturnMapper.selectSalesReturnList(salesReturn);
		if (!CollectionUtils.isEmpty(salesReturns)) {
			BigDecimal walletTotalAmount = salesReturns.stream().map(SalesReturn::getWalletAmount)
					.reduce(BigDecimal.ZERO, BigDecimal::add);
			if (walletPay.doubleValue() > 0) {
				BigDecimal subtract = salesOrder.getWalletPay().subtract(walletTotalAmount);
				vo.setWalletRefundableAmount(subtract);
			}

			BigDecimal cashTotalAmount = salesReturns.stream().map(SalesReturn::getCashAmount)
					.reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal cashSubtract = salesOrder.getPendingAmount().subtract(cashTotalAmount);
			vo.setCashRefundableAmount(cashSubtract);
		} else {
			vo.setWalletRefundableAmount(salesOrder.getWalletPay());
			vo.setCashRefundableAmount(salesOrder.getPendingAmount());
		}


		vo.setDeliverDetailList(deliverDetailList);
		return vo;
	}


	/**
	 * 查询销售单信息列表
	 *
	 * @param salesOrder 销售单信息
	 * @return 销售单信息
	 */
	@DataScope(deptAlias = "d", userAlias = "u")
	@Override
	public List<SalesOrder> selectSalesOrderList(SalesOrder salesOrder) {
		Map<String, Object> params = salesOrder.getParams();
		if (Objects.nonNull(params)) {
			if (params.get("dataScope") != null) {
				String filterSQL = (String) params.get("dataScope");
				if (filterSQL.indexOf("d.dept_id") > -1) {
					SysUser user = SecurityUtils.getLoginUser().getUser();
					filterSQL = filterSQL.replace("AND (", "AND (" + " a.collaborate_dept_id =" + user.getDeptId() +
                            " or ");
					params.put("dataScope", filterSQL);
					salesOrder.setParams(params);
				}
			}
		}
		return salesOrderMapper.selectSalesOrderList(salesOrder);
	}

	@Override
	public void export111(SalesOrder salesOrder, HttpServletResponse res) {
		try {

			res.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
			res.setCharacterEncoding("utf-8");
			String fileName = URLEncoder.encode("test", "UTF-8").replaceAll("\\+", "%20");
			res.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
			List<ReportOrderBO> orderList = new ArrayList<>();
			List<SalesOrderDetailVo> list = salesOrderMapper.selectOrderDetailList(salesOrder);

			for (SalesOrderDetailVo detailVo : list) {
				ReportOrderBO orderBO = new ReportOrderBO();
				BeanUtils.copyProperties(detailVo, orderBO);
				orderList.add(orderBO);
			}

			com.xz.sales.util.ExcelUtil.reportExcel(orderList, res);
		} catch (Exception e) {
			log.error(e.getMessage());
			res.reset();
			//            res.setContentType("application/json");
			//            res.setCharacterEncoding("utf-8");
			//            String origin = req.getHeader("Origin");
			//            res.setHeader("Access-Control-Allow-Origin", origin);
			e.printStackTrace();
		}
	}

	@Override
	public void export222(SalesOrder salesOrder, HttpServletResponse res) {
		try {

			List<SalesOrderDetailVo> list = salesOrderMapper.selectOrderDetailList(salesOrder);
			//2.定义基础数据


			// 1-待付款,2-销售处理,3-未交付,4-已交付,5-售后中,6-已售后 7-已取消
			Map salesOrderMap = new HashMap();
			salesOrderMap.put(null, "");
			salesOrderMap.put(1, "待付款");
			salesOrderMap.put(2, "销售处理");
			salesOrderMap.put(3, "未交付");
			salesOrderMap.put(4, "已交付");
			salesOrderMap.put(5, "售后中");
			salesOrderMap.put(6, "已售后");
			salesOrderMap.put(7, "已取消");

			Map sexMap = new HashMap();
			sexMap.put(null, "");
			sexMap.put(1, "男");
			sexMap.put(2, "女");
			// 1.门店自取 2.邮寄
			Map deliveryMethodMap = new HashMap();
			deliveryMethodMap.put(null, "");
			deliveryMethodMap.put(1, "门店自取");
			deliveryMethodMap.put(2, "邮寄");

			Map machingMap = new HashMap();
			machingMap.put(null, "");
			machingMap.put(0, "不加工");
			machingMap.put(1, "加工");

			Map preferentialTypeMap = new HashMap();
			preferentialTypeMap.put(null, "");
			preferentialTypeMap.put(1, "会员折扣");
			preferentialTypeMap.put(2, "积分抵扣");
			preferentialTypeMap.put(3, "手动折扣");


			Map provideMap = new HashMap();
			provideMap.put(null, "");
			provideMap.put(1, "是");
			provideMap.put(2, "否");

			// 处理数据
			Map<Long, List<SalesOrderExportBO.SalesDetail>> salesMap = new HashMap<>();

			List<SalesOrderExportBO> boList = new ArrayList<>();


			for (SalesOrderDetailVo o : list) {
				SalesOrderExportBO.SalesDetail salesDetail = new SalesOrderExportBO.SalesDetail();
				o.setMachiningTypeStr((String) machingMap.get(o.getMachiningType()));

				o.setSalesStatusStr((String) salesOrderMap.get(o.getSalesStatus()));
				o.setPatientName(o.getPatientName() + "/" + sexMap.get(o.getSex()) + "/" + o.getCurrentAge() + "岁");
				o.setDeliveryMethodStr((String) deliveryMethodMap.get(o.getDeliveryMethod()));
				o.setIsProvideOneselfStr((String) provideMap.get(o.getIsProvideOneself()));
				o.setPreferentialTypeStr((String) preferentialTypeMap.get(o.getPreferentialType()));
				BeanUtils.copyProperties(o, salesDetail);

				String useReceiveGift = o.getUseReceiveGift();
				if (StringUtils.isNotEmpty(useReceiveGift)) {
					List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
					StringBuilder stringBuilder = new StringBuilder();
					for (GiftReceive receive : giftReceives) {
						stringBuilder.append(receive.getGiftName()).append(";");
					}
					salesDetail.setUseReceiveGift(stringBuilder.toString());
				}
				if (!CollectionUtils.isEmpty(salesMap.get(o.getId()))) {
					List<SalesOrderExportBO.SalesDetail> salesDetails = salesMap.get(o.getId());
					salesDetails.add(salesDetail);
					salesMap.put(o.getId(), salesDetails);
				} else {
					List<SalesOrderExportBO.SalesDetail> salesDetails = new ArrayList<>();
					salesDetails.add(salesDetail);
					salesMap.put(o.getId(), salesDetails);
				}
			}


			for (Map.Entry<Long, List<SalesOrderExportBO.SalesDetail>> entry : salesMap.entrySet()) {
				Long key = entry.getKey();
				SalesOrderDetailVo detailVo = list.stream().filter(o -> o.getId().equals(key)).findFirst().get();
				SalesOrderExportBO bo = new SalesOrderExportBO();
				BeanUtils.copyProperties(detailVo, bo);
				bo.setSalesDetailList(entry.getValue());
				boList.add(bo);
			}

			String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒"));
			String fileName = "销售单数据_" + date;

			SalesExcelUtils.exportExcel(fileName + ".xlsx", res, SalesOrderExportBO.class, boList, fileName);


		} catch (Exception e) {
			log.error(e.getMessage());
			res.reset();
			//            res.setContentType("application/json");
			//            res.setCharacterEncoding("utf-8");
			//            String origin = req.getHeader("Origin");
			//            res.setHeader("Access-Control-Allow-Origin", origin);
			e.printStackTrace();
		}
	}


	@Override
	public void export(SalesOrder salesOrder, HttpServletResponse response) {

		List<SalesOrderDetailVo> list = salesOrderMapper.selectOrderDetailList(salesOrder);
		//2.定义基础数据


		// 1-待付款,2-销售处理,3-未交付,4-已交付,5-售后中,6-已售后 7-已取消
		Map salesOrderMap = new HashMap();
		salesOrderMap.put(null, "");
		salesOrderMap.put(1, "待付款");
		salesOrderMap.put(2, "销售处理");
		salesOrderMap.put(3, "未交付");
		salesOrderMap.put(4, "已交付");
		salesOrderMap.put(5, "售后中");
		salesOrderMap.put(6, "已售后");
		salesOrderMap.put(7, "已取消");

		Map sexMap = new HashMap();
		sexMap.put(null, "");
		sexMap.put(1, "男");
		sexMap.put(2, "女");
		// 1.门店自取 2.邮寄
		Map deliveryMethodMap = new HashMap();
		deliveryMethodMap.put(null, "");
		deliveryMethodMap.put(1, "门店自取");
		deliveryMethodMap.put(2, "邮寄");

		Map machingMap = new HashMap();
		machingMap.put(null, "");
		machingMap.put(0, "不加工");
		machingMap.put(1, "加工");

		Map preferentialTypeMap = new HashMap();
		preferentialTypeMap.put(null, "");
		preferentialTypeMap.put(1, "会员折扣");
		preferentialTypeMap.put(2, "积分抵扣");
		preferentialTypeMap.put(3, "手动折扣");


		Map provideMap = new HashMap();
		provideMap.put(null, "");
		provideMap.put(1, "是");
		provideMap.put(2, "否");

		List<String> rowHead = CollUtil.newArrayList("销售门店", "销售员", "制单时间", "订单状态", "销售单号", "客户信息", "手机号码", "关联会员卡号",
                "会员等级", "出生日期", "交付方式", "客人提供镜框", "备注", "商品总价", "优惠方式", "优惠金额", "抹零金额", "实收金额", "钱包", "现金", "银行卡", "E" +
                        "支付", "商品名称", "采购参数", "仓库", "加工类型", "售价", "数量", "赠品核销", "优惠", "小计", "备注");
		//3.通过ExcelUtil.getBigWriter()创建Writer对象，BigExcelWriter用于大数据量的导出，不会引起溢出；
		ExcelWriter writer = ExcelUtil.getBigWriter(65536);
		writer.writeHeadRow(new LinkedList());
		//4.写入标题
		writer.writeHeadRow(rowHead);

		// 合并表头
		writer.merge(0, 0, 0, 17, "订单信息", true);
		writer.merge(0, 0, 18, 21, "收款信息", true);
		writer.merge(0, 0, 22, 31, "商品信息", true);


		ServletOutputStream out = null;
		//5.实现核心逻辑
		try {
			//6.定义容器保存人物数据
			List<List<Object>> rows = new LinkedList<>();
			//7.按照班级进行分组
			LinkedHashMap<String, List<SalesOrderDetailVo>> classList =
                    list.stream().collect(Collectors.groupingBy(item -> item.getSalesNo(),
					LinkedHashMap::new, Collectors.toList()));
			//8.定义起始行（方便分组后合并时从哪一行开始）
			//因为标题已经占了一行，所以数据从第二行开始写（excel第一行索引为0）
			//因需要合并到人物分数单元格所以需定义如下起始坐标
			int indexSalesDeptName = 2;   //销售门店起始行
			int indexSalesUserName = 2;
			int indexSalesCreateTime = 2;
			int indexSalesStatus = 2;
			int indexSalesNo = 2;
			int indexPatientInfo = 2;
			int indexPatientPhone = 2;
			int indexMemberCardNo = 2;
			int indexMemberLevel = 2;
			int indexBirthday = 2;
			int indexDeliveryMethod = 2;
			int indexIsProvideOneself = 2;
			int indexSalesRemark = 2;
			int indexProductTotalAmount = 2;
			int indexPreferentialType = 2;
			int indexPreferentialAmount = 2;
			int indexreduceAmount = 2;
			int indexcollectionAmount = 2;
			int indexwalletPay = 2;
			int indexDish = 2;
			int indexBank = 2;
			int indexEPay = 2;
			//9.遍历按班级名分组后的list（用entrySet效率比keySet效率高）
			for (Map.Entry<String, List<SalesOrderDetailVo>> classNameListEntry : classList.entrySet()) {
				//10.获取按照班级名分组后的集合
				List<SalesOrderDetailVo> classValue = classNameListEntry.getValue();
				//11.计算此集合的长度
				int classSize = classValue.size();
				//12.如果只有一行数据不能调用merge方法合并数据，否则会报错
				if (classSize == 1) {
					indexSalesDeptName += classSize;
					indexSalesUserName += classSize;
					indexSalesCreateTime += classSize;
					indexSalesStatus += classSize;
					indexSalesNo += classSize;
					indexPatientInfo += classSize;
					indexPatientPhone += classSize;
					indexMemberCardNo += classSize;
					indexMemberLevel += classSize;
					indexBirthday += classSize;
					indexDeliveryMethod += classSize;
					indexIsProvideOneself += classSize;
					indexSalesRemark += classSize;
					indexProductTotalAmount += classSize;
					indexPreferentialType += classSize;
					indexPreferentialAmount += classSize;
					indexreduceAmount += classSize;
					indexcollectionAmount += classSize;
					indexwalletPay += classSize;
					indexDish += classSize;
					indexBank += classSize;
					indexEPay += classSize;
				} else {
					//13.根据班级名称进行合并单元格
					//合并行，第一个参数是合并行的开始行号（行号从0开始），第二个参数是合并行的结束行号，第三个参数是合并的列号开始(列号从0开始)，
					//第四个参数是合并的列号结束，第五个参数是合并后的内容，null不设置，第六个参数指是否支持设置样式，true指的是。

					//15.因为班级分数与班级名称相关联，所以不需要对班级分数分组，直接在此基础上对班级分数合并
					writer.merge(indexSalesDeptName, indexSalesDeptName + classSize - 1, 0, 0, null, true);
					indexSalesDeptName += classSize;

					writer.merge(indexSalesUserName, indexSalesUserName + classSize - 1, 1, 1, null, true);
					indexSalesUserName += classSize;

					writer.merge(indexSalesCreateTime, indexSalesCreateTime + classSize - 1, 2, 2, null, true);
					indexSalesCreateTime += classSize;

					writer.merge(indexSalesStatus, indexSalesStatus + classSize - 1, 3, 3, null, true);
					indexSalesStatus += classSize;

					writer.merge(indexSalesNo, indexSalesNo + classSize - 1, 4, 4, null, true);
					indexSalesNo += classSize;

					writer.merge(indexPatientInfo, indexPatientInfo + classSize - 1, 5, 5, null, true);
					indexPatientInfo += classSize;

					writer.merge(indexPatientPhone, indexPatientPhone + classSize - 1, 6, 6, null, true);
					indexPatientPhone += classSize;

					writer.merge(indexMemberCardNo, indexMemberCardNo + classSize - 1, 7, 7, null, true);
					indexMemberCardNo += classSize;

					writer.merge(indexMemberLevel, indexMemberLevel + classSize - 1, 8, 8, null, true);
					indexMemberLevel += classSize;

					writer.merge(indexBirthday, indexBirthday + classSize - 1, 9, 9, null, true);
					indexBirthday += classSize;

					writer.merge(indexDeliveryMethod, indexDeliveryMethod + classSize - 1, 10, 10, null, true);
					indexDeliveryMethod += classSize;

					writer.merge(indexIsProvideOneself, indexIsProvideOneself + classSize - 1, 11, 11, null, true);
					indexIsProvideOneself += classSize;

					writer.merge(indexSalesRemark, indexSalesRemark + classSize - 1, 12, 12, null, true);
					indexSalesRemark += classSize;

					writer.merge(indexProductTotalAmount, indexProductTotalAmount + classSize - 1, 13, 13, null, true);
					indexProductTotalAmount += classSize;

					writer.merge(indexPreferentialType, indexPreferentialType + classSize - 1, 14, 14, null, true);
					indexPreferentialType += classSize;

					writer.merge(indexPreferentialAmount, indexPreferentialAmount + classSize - 1, 15, 15, null, true);
					indexPreferentialAmount += classSize;

					writer.merge(indexreduceAmount, indexreduceAmount + classSize - 1, 16, 16, null, true);
					indexreduceAmount += classSize;

					writer.merge(indexcollectionAmount, indexcollectionAmount + classSize - 1, 17, 17, null, true);
					indexcollectionAmount += classSize;

					writer.merge(indexwalletPay, indexwalletPay + classSize - 1, 18, 18, null, true);
					indexwalletPay += classSize;

					writer.merge(indexDish, indexDish + classSize - 1, 19, 19, null, true);
					indexDish += classSize;

					writer.merge(indexBank, indexBank + classSize - 1, 20, 20, null, true);
					indexBank += classSize;

					writer.merge(indexEPay, indexEPay + classSize - 1, 21, 21, null, true);
					indexEPay += classSize;

				}
				classValue.stream().forEach(o -> {
					String useReceiveGift = o.getUseReceiveGift();
					if (StringUtils.isNotEmpty(useReceiveGift)) {
						List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
						StringBuilder stringBuilder = new StringBuilder();
						for (GiftReceive receive : giftReceives) {
							stringBuilder.append(receive.getGiftName()).append(";");
						}
						o.setUseReceiveGift(stringBuilder.toString());
					}
				});

				//18.保存数据
				classValue.forEach(
						sList -> {
							List<Object> rowA = null;
							rowA = CollUtil.newArrayList(

									sList.getSalesDeptName(),
									sList.getSalesUserName(),
									sList.getSalesCreateTime(),
									salesOrderMap.get(sList.getSalesStatus()),
									sList.getSalesNo(),
									sList.getPatientName() + "/" + sexMap.get(sList.getSex()) + "/" + sList.getCurrentAge() + "岁",
									sList.getPatientPhone(),
									sList.getMemberCardNo(),
									sList.getMemberLevel(),
									sList.getBirthday(),
									deliveryMethodMap.get(sList.getDeliveryMethod()),
									provideMap.get(sList.getIsProvideOneself()),
									sList.getSalesRemark(),
									sList.getProductTotalAmount(),
									preferentialTypeMap.get(sList.getPreferentialType()),
									sList.getPreferentialAmount(),
									sList.getReduceAmount(),
									sList.getCollectionAmount(),
									sList.getWalletPay(),
									sList.getDish(),
									sList.getBank(),
									sList.getEPay(),
									sList.getProductName(),
									sList.getProductParam(),
									sList.getWarehouseName(),
									machingMap.get(sList.getMachiningType()),
									sList.getSellingPrice(),
									sList.getSellingNum(),
									sList.getUseReceiveGift(),
									sList.getDiscountAmount(),
									sList.getSubtotal(),
									sList.getRemark()

							);
							rows.add(rowA);
						}
				);
			}
			//19.导出数据
			//logger.info("导出数据：{}",rows.toString());
			// 一次性写出内容，使用默认样式，强制输出标题
			//            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
			//            excelWriter.fill(rows, fillConfig, writeSheet);
			writer.write(rows, true);
			//response为HttpServletResponse对象
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			//获取当前日期作为文件名
			Date currentDate = new Date();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			String date = sdf.format(currentDate);
			//test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
			//response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
			response.setHeader("Content-Disposition", "attachment;filename=report_" + date + ".xlsx");
			out = response.getOutputStream();
			writer.flush(out, true);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//关闭输出Servlet流
			IoUtil.close(out);
			//关闭writer，释放内存
			writer.close();
		}
	}

	@DataScope(deptAlias = "d")
	@Override
	public List<SalesServiceVo> serviceList(SalesOrder salesOrder) {
		return salesOrderMapper.serviceList(salesOrder);
	}

	/**
	 * 新增销售单信息
	 *
	 * @param param 销售单信息
	 * @return 结果
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult insertSalesOrder(SalesOrderParam param) {
		Date currDate = new Date();
		SalesOrder salesOrder = new SalesOrder();
		BeanUtils.copyProperties(param, salesOrder);
		salesOrder.setDeptId(SecurityUtils.getLoginUser().getDeptId());
		salesOrder.setCreateBy(SecurityUtils.getLoginUser().getUserId());
		salesOrder.setSalesNo(RedisCode.getCode("XS"));
		//新增时，剩余积分一定是总积分
		salesOrder.setResidualIntegral(salesOrder.getDeductionIntegral());
		PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
		int nowYear = DateUtil.year(new Date());
		int year = 0;
		if (Objects.nonNull(patientInfo.getBirthday())) {
			year = DateUtil.ageOfNow(patientInfo.getBirthday());
		}
		StringBuilder memberName = new StringBuilder();
		if (Objects.nonNull(patientInfo)) {
			String sex = "";
			Integer sexNum = patientInfo.getSex();
			if (sexNum == null || sexNum == 0) {
				sex = "-";
			} else if (sexNum == 1) {
				sex = "男";
			} else if (sexNum == 2) {
				sex = "女";
			}
			memberName.append(patientInfo.getPatientName()).append("/").append(sex).append("/").append(year).append(
			        "岁");
		}
		salesOrder.setPatientName(memberName.toString());

		// 判断需要售价审批不
		SalesRuleSetting queryRule = new SalesRuleSetting();
		queryRule.setDeptId(SecurityUtils.getDeptId());
		if (param.getPreferentialType().equals(3)) {
			BigDecimal discount = param.getDiscount();
			// 查询设置门店审批阀值
			queryRule.setRuleSerialNo(1);
			SalesRuleSetting salesRuleSetting = salesRuleSettingMapper.queryMyRule(queryRule);
			if (Objects.nonNull(salesRuleSetting)) {
				String ruleValue = salesRuleSetting.getRuleValue();
				JSONObject jsonObject = JSONObject.parseObject(ruleValue);
				String approvalDiscount = jsonObject.getString("approvalDiscount");
				BigDecimal settingDiscount = new BigDecimal(approvalDiscount);
				if (discount.doubleValue() < settingDiscount.doubleValue()) {
					salesOrder.setPriceApprovalStatus(1);
				}
			}
		}
		salesOrder.setCreateTime(currDate);
		int i = salesOrderMapper.insertSalesOrder(salesOrder);
		queryRule.setRuleSerialNo(2);
		SalesRuleSetting salesRuleSetting = salesRuleSettingMapper.queryMyRule(queryRule);
		List<String> stringList = new ArrayList<>();
		stringList.add("-99");
		if (Objects.nonNull(salesRuleSetting)) {
			String ruleValue = salesRuleSetting.getRuleValue();
			JSONObject jsonObject = JSONObject.parseObject(ruleValue);
			String approvalDiscount = jsonObject.getString("uploadCategory");
			String[] split = approvalDiscount.split(",");
			stringList = Stream.of(split).collect(Collectors.toList());

		}
		Long userId = SecurityUtils.getUserId();
		if (i > 0) {
			List<SalesOrderDetail> detailList = param.getDetailList();
			for (SalesOrderDetail orderDetail : detailList) {
				orderDetail.setSalesId(salesOrder.getId());
				orderDetail.setSalesNo(salesOrder.getSalesNo());
				orderDetail.setDeptId(salesOrder.getDeptId());
				orderDetail.setTenantId(salesOrder.getTenantId());
				// 判断使用了会员卡 去核销
				List<Long> giftReceiveList = orderDetail.getGiftReceiveList();
				if (!CollectionUtils.isEmpty(giftReceiveList)) {
					String join = StringUtils.join(giftReceiveList, ",");
					orderDetail.setUseReceiveGift(join);
					// 需要把核销商品 变成 核销中
					List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(join);
					for (GiftReceive receive : giftReceives) {
						receive.setStatus(3);
						receive.setRelatedSalesNo(salesOrder.getSalesNo());
						receive.setWrittenOffDeptId(salesOrder.getDeptId());
						receive.setWrittenOffUserId(userId);
						giftReceiveMapper.updateById(receive);
					}
				}
				//  判断需要上传附件  然后设置 isUploadFile值
				Product product = productMapper.selectById(orderDetail.getProductId());
				if (Objects.nonNull(product.getCategoryId())) {
					if (stringList.contains(product.getCategoryId().toString()) && orderDetail.getProductPurchaseType().equals(2)) {
						orderDetail.setProductStatus(3);
						orderDetail.setIsUploadFile(1);
					}
				}
				orderDetail.setBeforeTreatmentNo(salesOrder.getSalesNo());
				orderDetail.setAfterTreatmentNo(salesOrder.getSalesNo());
				orderDetail.setCreateTime(currDate);
				salesOrderDetailMapper.insertSalesOrderDetail(orderDetail);
				SalesOriginalOrderDetail originalOrderDetail = new SalesOriginalOrderDetail();
				BeanUtils.copyProperties(orderDetail, originalOrderDetail);
				originalOrderDetail.setDetailId(orderDetail.getId());
				originalOrderDetail.setCreateTime(currDate);
				i = originalOrderDetailMapper.insertSalesOriginalOrderDetail(originalOrderDetail);
				if (i <= 0) {
					return AjaxResult.error("操作失败！");
				}
			}
			// 更新库存
			List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectBySalesId(salesOrder.getId());
			boolean b = occupyPurchaseProduct(salesOrder, salesOrderDetails, 1);
			if (false == b) {
				throw new ServiceException("新增失败！原因：增加销售单库存流水失败。");
			}
		}
		return AjaxResult.success(salesOrder.getId());
	}

	/**
	 * 确认收款
	 *
	 * @param param
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult confirmCollection(SalesOrderParam param) {
		Long id = param.getId();
		if (Objects.isNull(id)) {
			return AjaxResult.success("参数不能为空！");
		}
		SalesOrder salesOrder = baseMapper.selectById(param.getId());
		// 下面这块在收款的时候用
		if ((Objects.nonNull(param.getWalletPay()) && param.getWalletPay().doubleValue() > 0) ||
				Objects.nonNull(param.getDeductionIntegral()) && param.getDeductionIntegral().doubleValue() > 0) {
			// 说明使用了钱包支付 或者 积分抵扣
			MemberInfo memberInfo = memberInfoMapper.memberInfoByCardNo(salesOrder.getMemberCardNo());
			BigDecimal walletBalance = memberInfo.getWalletBalance();
			if (Objects.nonNull(param.getWalletPay()) && walletBalance.doubleValue() < param.getWalletPay().doubleValue()) {
				return AjaxResult.error("钱包余额不足！");
			} else {
				if (Objects.nonNull(param.getWalletPay()) && param.getWalletPay().doubleValue() > 0) {
					walletBalance = walletBalance.subtract(param.getWalletPay());
					memberInfo.setWalletBalance(walletBalance);
					// 新增消费流水新增
					int i = walletRecordService.addBizRecord(salesOrder.getMemberCardNo(), 4, 2,
                            salesOrder.getSalesNo(), param.getWalletPay(), salesOrder.getDeptId());
					if (i <= 0) {
						throw new ServiceException("销售单确认付款失败！原因：钱包销售扣款新增流水失败。");
					}
				}
			}
			BigDecimal integralBalance = memberInfo.getIntegralBalance();
			if (Objects.nonNull(param.getDeductionIntegral()) && integralBalance.doubleValue() < param.getDeductionIntegral().doubleValue()) {
				return AjaxResult.error("积分余额不足！");
			} else {
				if (Objects.nonNull(param.getDeductionIntegral()) && param.getDeductionIntegral().doubleValue() > 0) {
					integralBalance = integralBalance.subtract(param.getDeductionIntegral());
					memberInfo.setIntegralBalance(integralBalance);
					int x = integralRecordService.addBizRecord(3, param.getDeductionIntegral(),
                            salesOrder.getMemberCardNo(), salesOrder.getDeptId(), salesOrder.getSalesNo());
					if (x <= 0) {
						throw new ServiceException("销售单确认付款失败！原因：钱包销售扣款新增积分流水失败。");
					}
				}
			}
			memberInfoMapper.updateById(memberInfo);

			// 发送账户变动短信
			MemberMsgInfo msgInfo = new MemberMsgInfo();
			msgInfo.setId(memberInfo.getId());
			BeanUtils.copyProperties(memberInfo, msgInfo);
			msgInfo.setVariableIntegral(new BigDecimal("0"));
			msgInfo.setVariableAmount(param.getWalletPay());
			sysTenantNotifyItemService.sendMemberInfoMsg(msgInfo, 1, SecurityUtils.getLoginUser().getUser());
			//            WalletRecord walletRecord = new WalletRecord();
			//            walletRecord.setMemberCardNo(salesOrder.getMemberCardNo());
			//            walletRecord.setStatus(2);
			//            walletRecord.setRelatedNo(salesOrder.getSalesNo());
			//            walletRecord.setChangeValue(param.getWalletPay());
			//            walletRecord.setChangeValueType(2);
			//            walletRecord.setChangeType(4);
			//            walletRecord.setCreateBy(salesOrder.getCreateBy());
			//            walletRecord.setDeptId(salesOrder.getDeptId());
			//            walletRecordMapper.insert(walletRecord);
		}
		salesOrder.setOrderStatus(3);
		salesOrder.setPaymentType(param.getPaymentType());
		salesOrder.setPaymentTime(new Date());
		salesOrder.setWalletPay(param.getWalletPay());
		salesOrder.setPendingAmount(param.getPendingAmount());
		int i = salesOrderMapper.updateSalesOrder(salesOrder);
		Long patientId = salesOrder.getPatientId();
		// 更新客户患者累计消费值
		PatientInfo patientInfo = patientInfoMapper.selectById(patientId);
		BigDecimal accumulatedConsumption = patientInfo.getAccumulatedConsumption();
		patientInfo.setAccumulatedConsumption(accumulatedConsumption.add(salesOrder.getCollectionAmount()));
		patientInfoMapper.updateById(patientInfo);
		if (i > 0) {
			List<ProcessOrderItem> processOrderItemList = new ArrayList<>();
			List<SalesOrderDetail> needPurchaseDetailList = new ArrayList<>();

			List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectListBySales(salesOrder);
			salesOrderDetails.forEach(o -> {

				ProcessOrderItem processOrderItem = new ProcessOrderItem();
				BeanUtils.copyProperties(o, processOrderItem);
				//                if(o.getMachiningType().equals(1)){
				//                    // 需要加工更新销售单商品状态
				//                    o.setProductStatus(8);
				//                    if(o.getProductPurchaseType().equals(1)){
				//                        processOrderItem.setStatus(2);
				//                    }else {
				//                        processOrderItem.setStatus(3);
				//                    }
				//                    if(salesOrder.getDeptId().equals(o.getWarehouseId())){
				//                        o.setProductStatus(2);
				//                        processOrderItem.setStatus(1);
				//                    }
				//                    processOrderItem.setSalesOrderId(salesOrder.getId());
				//                    processOrderItem.setSalesOrderDetailId(o.getId());
				//                    processOrderItemList.add(processOrderItem);
				//                }
				//                if(o.getProductPurchaseType().equals(2)){
				//                    // 定制采购
				//                    o.setProductStatus(4);
				//                    needPurchaseDetailList.add(o);
				//                }else {

				// 不需要定制采购的 直接是待交付
				//                    if(o.getMachiningType().equals(0)){
				//                        o.setProductStatus(11);
				//                    }
				o.setProductStatus(11);
				//                }
				salesOrderDetailMapper.updateById(o);
			});
			//            if(!CollectionUtils.isEmpty(processOrderItemList)){
			//                ProcessOrder processOrder = new ProcessOrder();
			//                processOrder.setPatientId(patientId);
			//                processOrder.setPatientName(patientInfo.getPatientName());
			//                processOrder.setPatientPhone(patientInfo.getPhoneNumber());
			//                processOrder.setSalesId(salesOrder.getId());
			//                processOrder.setSalesNo(salesOrder.getSalesNo());
			//                Integer deliveryMethod = salesOrder.getDeliveryMethod();
			//                SysDept sysDept = sysDeptService.selectDeptById(salesOrder.getDeptId());
			//                if(deliveryMethod.equals(2)){
			//                    processOrder.setHarvestAddress(salesOrder.getMailingAddress());
			//                    processOrder.setRecipients(patientInfo.getPatientName());
			//                    processOrder.setRecipientsPhone(patientInfo.getPhoneNumber());
			//                }else {
			//                    processOrder.setHarvestAddress(sysDept.getEmail());
			//                    processOrder.setRecipients(sysDept.getLeader());
			//                    processOrder.setRecipientsPhone(sysDept.getPhone());
			//                }
			//                processOrder.setSalesDeptName(sysDept.getDeptName());
			//                processOrder.setChargeTime(salesOrder.getPaymentTime());
			//                processOrder.setSalesDeptId(salesOrder.getDeptId());
			//                processOrder.setIsProvideOneself(salesOrder.getIsProvideOneself());
			//                processOrder.setDeliveryMethod(salesOrder.getDeliveryMethod());
			//                processOrder.setProcessOrderItemList(processOrderItemList);
			//                // 添加加工单
			//                processOrderService.insertProcessOrder(processOrder);
			//            }
			//            // 生成定制采购单
			//            if(!CollectionUtils.isEmpty(needPurchaseDetailList)){
			//                processOrderService.salesCustomPurchasing(needPurchaseDetailList);
			//            }
			// 插入 费用账单管理
			ExpenseBill expenseBill = new ExpenseBill();
			expenseBill.setDeptId(salesOrder.getDeptId());
			expenseBill.setTenantId(salesOrder.getTenantId());
			expenseBill.setPatientId(salesOrder.getPatientId());
			expenseBill.setActCost(salesOrder.getCollectionAmount());
			expenseBill.setBizNo(salesOrder.getSalesNo());
			expenseBill.setBizType(1);
			expenseBill.setStatus(1);
			expenseBill.setBizId(salesOrder.getId());
			expenseBill.setReceivableCost(salesOrder.getProductTotalAmount());
			expenseBill.setPreferentialCost(salesOrder.getPreferentialAmount());
			expenseBill.setCreateBy(salesOrder.getCreateBy());
			expenseBillMapper.insertExpenseBill(expenseBill);

		}
		return AjaxResult.success("操作成功！");
	}

	/**
	 * 确认收款 带定制采购 后面用这个
	 *
	 * @param param
	 * @return
	 */
	@Override
	public AjaxResult confirmCollectionTwo(SalesOrderParam param) {
		Long id = param.getId();
		if (Objects.isNull(id)) {
			return AjaxResult.success("参数不能为空！");
		}
		SalesOrder salesOrder = baseMapper.selectById(param.getId());
		// 下面这块在收款的时候用
		if ((Objects.nonNull(param.getWalletPay()) && param.getWalletPay().doubleValue() > 0) ||
				Objects.nonNull(param.getDeductionIntegral()) && param.getDeductionIntegral().doubleValue() > 0) {
			// 说明使用了钱包支付 或者 积分抵扣
			MemberInfo memberInfo = memberInfoMapper.memberInfoByCardNo(salesOrder.getMemberCardNo());
			BigDecimal walletBalance = memberInfo.getWalletBalance();
			if (Objects.nonNull(param.getWalletPay()) && walletBalance.doubleValue() < param.getWalletPay().doubleValue()) {
				return AjaxResult.error("钱包余额不足！");
			} else {
				if (Objects.nonNull(param.getWalletPay()) && param.getWalletPay().doubleValue() > 0) {
					walletBalance = walletBalance.subtract(param.getWalletPay());
					memberInfo.setWalletBalance(walletBalance);
					// 新增消费流水新增
					int i = walletRecordService.addBizRecord(salesOrder.getMemberCardNo(), 4, 2,
                            salesOrder.getSalesNo(), param.getWalletPay(), salesOrder.getDeptId());
					if (i <= 0) {
						throw new ServiceException("销售单确认付款失败！原因：钱包销售扣款新增流水失败。");
					}
				}
			}
			BigDecimal integralBalance = memberInfo.getIntegralBalance();
			if (Objects.nonNull(param.getDeductionIntegral()) && integralBalance.doubleValue() < param.getDeductionIntegral().doubleValue()) {
				return AjaxResult.error("积分余额不足！");
			} else {
				if (Objects.nonNull(param.getDeductionIntegral()) && param.getDeductionIntegral().doubleValue() > 0) {
					integralBalance = integralBalance.subtract(param.getDeductionIntegral());
					memberInfo.setIntegralBalance(integralBalance);
					int x = integralRecordService.addBizRecord(3, param.getDeductionIntegral(),
                            salesOrder.getMemberCardNo(), salesOrder.getDeptId(), salesOrder.getSalesNo());
					if (x <= 0) {
						throw new ServiceException("销售单确认付款失败！原因：钱包销售扣款新增积分流水失败。");
					}
				}
			}
			memberInfoMapper.updateById(memberInfo);

			// 发送账户变动短信
			MemberMsgInfo msgInfo = new MemberMsgInfo();
			msgInfo.setId(memberInfo.getId());
			BeanUtils.copyProperties(memberInfo, msgInfo);
			// 以订单的门店为准
			msgInfo.setDeptId(salesOrder.getDeptId());
			msgInfo.setVariableIntegral(null == integralBalance ? new BigDecimal("0") : integralBalance);
			msgInfo.setVariableAmount(param.getWalletPay());
			sysTenantNotifyItemService.sendMemberInfoMsg(msgInfo, 1, SecurityUtils.getLoginUser().getUser());
		}
		salesOrder.setOrderStatus(3);
		salesOrder.setPaymentType(param.getPaymentType());
		salesOrder.setPaymentTime(new Date());
		salesOrder.setWalletPay(param.getWalletPay());
		salesOrder.setPendingAmount(param.getPendingAmount());
		int i = salesOrderMapper.updateSalesOrder(salesOrder);
		Long patientId = salesOrder.getPatientId();

		SysDept sysDept = sysDeptService.selectDeptById(salesOrder.getDeptId());
		// 更新客户患者累计消费值
		PatientInfo patientInfo = patientInfoMapper.selectById(patientId);
		BigDecimal accumulatedConsumption = patientInfo.getAccumulatedConsumption();
		patientInfo.setAccumulatedConsumption(accumulatedConsumption.add(salesOrder.getCollectionAmount()));
		patientInfoMapper.updateById(patientInfo);
		if (i > 0) {
			List<ProcessOrderItem> processOrderItemList = new ArrayList<>();
			List<SalesOrderDetail> needPurchaseDetailList = new ArrayList<>();

			// 查看自己权限仓库
			List<WarehouseDto> warehouseDtoList = warehouseMapper.selectDeptList(salesOrder.getDeptId());
			List<Long> mySelfWarehouse = new ArrayList<>();
			if (!CollectionUtils.isEmpty(warehouseDtoList)) {
				mySelfWarehouse = warehouseDtoList.stream().map(WarehouseDto::getId).distinct().collect(Collectors.toList());
			}

			List<Long> shareWarehouse = new ArrayList<>();
			List<WarehouseDto> shareWarehouseList = warehouseMapper.getShareWarehouseList();
			if (!CollectionUtils.isEmpty(shareWarehouseList)) {
				shareWarehouse = shareWarehouseList.stream().map(WarehouseDto::getId).distinct().collect(Collectors.toList());
			}

			List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectListBySales(salesOrder);
			boolean createSettingPurchase = true;
			for (SalesOrderDetail o : salesOrderDetails) {

				ProcessOrderItem processOrderItem = new ProcessOrderItem();
				BeanUtils.copyProperties(o, processOrderItem);
				if (o.getMachiningType().equals(1)) {
					// 需要加工更新销售单商品状态
					o.setProductStatus(8);
					if (o.getProductPurchaseType().equals(1)) {
						processOrderItem.setStatus(3);
					} else {
						processOrderItem.setStatus(2);
					}
					if (mySelfWarehouse.contains(o.getWarehouseId()) && !shareWarehouse.contains(o.getWarehouseId())) {// 如果是自己仓库的并且不是公共仓的 需要移交加工
						o.setProductStatus(2);
						processOrderItem.setStatus(1);
					}
					processOrderItem.setProcessNum(o.getSellingNum());
					processOrderItem.setSalesOrderId(salesOrder.getId());
					processOrderItem.setSalesOrderDetailId(o.getId());
					processOrderItem.setWarehouseId(o.getWarehouseId());
					processOrderItem.setWarehouseName(o.getWarehouseName());

					processOrderItemList.add(processOrderItem);
				}
				if (o.getProductPurchaseType().equals(2)) {
					// 定制采购
					o.setProductStatus(4);
					if (o.getIsUploadFile().equals(1)) {
						o.setProductStatus(3);
						createSettingPurchase = false;
					}
					needPurchaseDetailList.add(o);
				} else {
					// 不需要定制采购的 直接是待交付
					if (o.getMachiningType().equals(0)) {
						o.setProductStatus(11);
					}
				}
				//赋值实际小计，实际小计 = 小计
				o.setActualSubtotal(o.getSubtotal());
				salesOrderDetailMapper.updateById(o);
			}
			/*** 这边宝哥说直接调他的方法就好了 ↓ ***/
			// 生成加工单
			if (!CollectionUtils.isEmpty(processOrderItemList)) {
				ProcessOrder processOrder = new ProcessOrder();
				processOrder.setPatientId(patientId);
				processOrder.setPatientName(salesOrder.getPatientName());
				processOrder.setPatientPhone(patientInfo.getPhoneNumber());
				processOrder.setSalesId(salesOrder.getSalesUserId());
				processOrder.setSalesOrderId(salesOrder.getId());
				processOrder.setSalesNo(salesOrder.getSalesNo());
				processOrder.setIsProvideOneself(salesOrder.getIsProvideOneself());
				processOrder.setDeliveryMethod(salesOrder.getDeliveryMethod());
				processOrder.setRemark(salesOrder.getRemark());

				Integer deliveryMethod = salesOrder.getDeliveryMethod();
				if (deliveryMethod.equals(2)) {
					processOrder.setHarvestAddress(salesOrder.getMailingAddress());
					processOrder.setRecipients(patientInfo.getPatientName());
					processOrder.setRecipientsPhone(patientInfo.getPhoneNumber());
				} else {
					processOrder.setHarvestAddress(sysDept.getEmail());
					processOrder.setRecipients(sysDept.getLeader());
					processOrder.setRecipientsPhone(sysDept.getPhone());
				}
				processOrder.setSalesDeptName(sysDept.getDeptName());
				processOrder.setChargeTime(salesOrder.getPaymentTime());
				processOrder.setSalesDeptId(salesOrder.getDeptId());
				processOrder.setIsProvideOneself(salesOrder.getIsProvideOneself());
				processOrder.setPatientProvideOneself(salesOrder.getProvideFrames());
				processOrder.setDeliveryMethod(salesOrder.getDeliveryMethod());
				processOrder.setProcessOrderItemList(processOrderItemList);
				List<Integer> collect =
                        processOrderItemList.stream().map(ProcessOrderItem::getStatus).collect(Collectors.toList());
				if (collect.contains(1) || collect.contains(2)) {
					processOrder.setProcessingStatus(1);
				}
				// 添加加工单
				processOrderService.insertProcessOrder(processOrder);
			}
			// 生成定制采购单
			if (createSettingPurchase == true) {
				if (!CollectionUtils.isEmpty(needPurchaseDetailList)) {
					SalesPurchaseApplyVo salesPurchaseApplyVo = new SalesPurchaseApplyVo();
					salesPurchaseApplyVo.setSalesNo(salesOrder.getSalesNo());
					salesPurchaseApplyVo.setSalesDeptId(salesOrder.getDeptId());
					salesPurchaseApplyVo.setSalesOrderId(salesOrder.getId());
					salesPurchaseApplyVo.setOrderDetailList(needPurchaseDetailList);
					purchaseApplyService.addSalesPurchaseApply(salesPurchaseApplyVo);
				}
			}

			/*** 这边宝哥说直接调他的方法就好了 ↑  ***/
			// 插入 费用账单管理
			ExpenseBill expenseBill = new ExpenseBill();
			expenseBill.setDeptId(salesOrder.getDeptId());
			expenseBill.setTenantId(salesOrder.getTenantId());
			expenseBill.setPatientId(salesOrder.getPatientId());
			expenseBill.setActCost(salesOrder.getCollectionAmount());
			expenseBill.setBizNo(salesOrder.getSalesNo());
			expenseBill.setBizType(1);
			expenseBill.setStatus(1);
			expenseBill.setBizId(salesOrder.getId());
			expenseBill.setReceivableCost(salesOrder.getProductTotalAmount());
			expenseBill.setPreferentialCost(salesOrder.getPreferentialAmount());
			expenseBill.setCreateBy(salesOrder.getCreateBy());
			expenseBillMapper.insertExpenseBill(expenseBill);

		}
		List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectBySalesId(salesOrder.getId());
		Integer newOrderStatus = ProcessOrderUtil.processOrderStatusByDetails(salesOrderDetails);
		salesOrderMapper.updateOrderStatus(salesOrder.getId(), newOrderStatus);
		return AjaxResult.success("操作成功！");
	}


	private boolean occupyPurchaseProduct(SalesOrder salesOrder, List<SalesOrderDetail> salesOrderDetails,
                                          Integer editType) {

		for (SalesOrderDetail salesDetail : salesOrderDetails) {
			if (salesDetail.getProductPurchaseType().equals(2)) {
				continue;
			}
			if (editType.equals(1)) {
				PurchaseProduct queryProductParam = new PurchaseProduct();
				// todo 尝试修改下单时“商品选择查询”与“下单提交”商品不一致bug
				queryProductParam.setProductName(salesDetail.getProductName());
				queryProductParam.setProductParam(salesDetail.getProductParam());
				queryProductParam.setBatchNumber(salesDetail.getBatchNumber());
				queryProductParam.setWarehouseId(salesDetail.getWarehouseId());

				//BeanUtils.copyProperties(salesDetail,queryProductParam);
				List<PurchaseProduct> purchaseProductList =
                        purchaseProductMapper.getSalesListByParam(queryProductParam);
				if (CollectionUtils.isEmpty(purchaseProductList)) {
					throw new ServiceException("销售单提交失败！原因：商品名称:" + queryProductParam.getProductName() + ",参数:" + queryProductParam.getProductParam() + "库存为0，请重新选择商品！");
				} else {
					Integer sellingNum = salesDetail.getSellingNum();
					Integer nowNum = 0;
					for (PurchaseProduct purchaseProductInfo : purchaseProductList) {
						nowNum += purchaseProductInfo.getAvailableStock();
					}
					if (sellingNum > nowNum) {
						throw new ServiceException("销售单提交失败！原因：商品名称:" + queryProductParam.getProductName() + ",参数:" + queryProductParam.getProductParam() + "库存不足，请重新选择商品！");
					}
				}
				List<PurchaseProduct> purchaseProducts = iRepertoryFlowService.convertFlowData(purchaseProductList,
                        salesDetail.getSellingNum(), salesOrder.getSalesNo(), salesDetail.getId());
				// setInventoryQuantity
				for (PurchaseProduct purchaseProduct : purchaseProducts) {
					SalesPurchase salesPurchase = new SalesPurchase();
					salesPurchase.setSalesId(salesOrder.getId());
					salesPurchase.setDetailId(salesDetail.getId());
					salesPurchase.setPurchaseProductId(purchaseProduct.getId());
					salesPurchase.setPurchaseProductNum(purchaseProduct.getInventoryQuantity());
					salesPurchaseMapper.insert(salesPurchase);
				}
			} else {
                List<PurchaseProduct> purchaseProductList = getSalesPurchaseProducts(salesOrder.getId(), salesDetail.getId());
                for (PurchaseProduct purchaseProduct : purchaseProductList) {
					Integer inventoryQuantity = purchaseProduct.getInventoryQuantity();
					Integer availableStock = purchaseProduct.getAvailableStock();
					purchaseProduct.setAvailableStock(availableStock + inventoryQuantity);
					purchaseProductMapper.updateById(purchaseProduct);
				}
			}
		}

		return true;

	}

	/**
	 * 生成日志（根据销售单修改）
	 * @param salesOrder
	 * @param salesOrderDetails
	 * @param editType
	 * @return
	 */
	private boolean insertFlowBySalesUpdate(SalesOrder salesOrder, List<SalesOrderDetail> salesOrderDetails, EditTypeEnum editType) {
		Date currDate = new Date();
		// 因为这边是确认收货 所以先更新采购库存
		BigDecimal discount = salesOrder.getDiscount();
		List<SalesOrderDetail> forSalesOrderDetails = new ArrayList<>();
		for (SalesOrderDetail salesDetail : salesOrderDetails) {
			if (salesDetail.getProductPurchaseType().equals(2)) {
				// 因为前面定制采购数据没有入库 所以只更新状态 这边处理515之前定制采购的数据
				DateTime parse = DateUtil.parse("2024-05-15 00:00:00", "yyyy-MM-dd HH:mm:ss");
				if (salesOrder.getCreateTime().getTime() < parse.getTime()) {
					salesOrderDetailMapper.updateById(salesDetail);
					continue;
				} else {
					// 如果是 定制采购流水
					// 定制采购交付需要拆分销售明细单方便后面好
					Integer sellingNum = salesDetail.getSellingNum();
					if (sellingNum > 1) {
                        List<PurchaseProduct> purchaseProducts = getSalesPurchaseProducts(salesOrder.getId(), salesDetail.getId());
                        if (!CollectionUtils.isEmpty(purchaseProducts)) {
							// 重新计算 优惠金额 和 小计
							BigDecimal discountAmount = salesDetail.getDiscountAmount();
							BigDecimal subtotal = salesDetail.getSubtotal();
							BigDecimal giftDeductionTotal = salesDetail.getGiftDeductionTotal();
							BigDecimal reductionAmount = salesDetail.getReductionAmount();

							String useReceiveGift = salesDetail.getUseReceiveGift();
							BigDecimal sellingPrice = salesDetail.getSellingPrice();

							for (PurchaseProduct purchaseProduct : purchaseProducts) {
								SalesOrderDetail newOrderDetail = new SalesOrderDetail();
								BeanUtils.copyProperties(salesDetail, newOrderDetail);
								Integer returnNum = purchaseProduct.getInventoryQuantity();
								if (returnNum == sellingNum) {
									salesDetail.setWarehouseName(purchaseProduct.getWarehouseName());
									salesDetail.setWarehouseId(purchaseProduct.getWarehouseId());
									salesDetail.setBatchNumber(purchaseProduct.getBatchNumber());
									salesDetail.setValidity(purchaseProduct.getValidity());
									salesDetail.setUnit(purchaseProduct.getUnit());
									salesDetail.setSellingNum(returnNum);
									forSalesOrderDetails.add(salesDetail);
									salesOrderDetailMapper.updateById(salesDetail);
									break;
								}
								int needReturnCard = 0;
								if (StringUtils.isNotEmpty(useReceiveGift)) {
									// 使用了优惠卡
									String[] split = useReceiveGift.split(",");
									List<String> stringList = Stream.of(split).collect(Collectors.toList());
									int length = split.length;
									// 用了几张优惠卡
									int num = sellingNum - returnNum;
									int cardUseNum = length - num; // 要退的卡数
									needReturnCard = cardUseNum;
									List<String> returnGiftList = new ArrayList<>();
									if (cardUseNum > 0) {
										BigDecimal giftDeductionTotalDivide = giftDeductionTotal.divide(BigDecimal.valueOf(length), 4, BigDecimal.ROUND_HALF_UP);
										BigDecimal returnGiftDeductionTotal = giftDeductionTotalDivide.multiply(BigDecimal.valueOf(cardUseNum));
										newOrderDetail.setGiftDeductionTotal(returnGiftDeductionTotal);
										giftDeductionTotal = giftDeductionTotal.subtract(returnGiftDeductionTotal);
										salesDetail.setGiftDeductionTotal(giftDeductionTotal);
										// 需要退会员卡了
										for (int j = 0; j < cardUseNum; j++) {
											returnGiftList.add(split[j]);
										}
										newOrderDetail.setUseReceiveGift(StringUtils.join(returnGiftList, ","));
									} else {
										newOrderDetail.setUseReceiveGift(null);
										newOrderDetail.setGiftDeductionTotal(new BigDecimal(0.00));
									}
									// 更改原来商品明细的使用会员卡号
									stringList.removeAll(returnGiftList);
									useReceiveGift = StringUtils.join(stringList, ",");
									salesDetail.setUseReceiveGift(useReceiveGift);

								}
								BigDecimal returnReductionAmount =
                                        reductionAmount.divide(BigDecimal.valueOf(sellingNum), 2,
                                                BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(returnNum));
								BigDecimal newSubtotal = new BigDecimal("0.00");// 重新算
								if (!salesDetail.getDetailType().equals(1)) {
									if (discount != null && discount.doubleValue() > 0) {

										newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newOrderDetail.getGiftDeductionTotal()).multiply(discount).divide(new BigDecimal("10"), 4, BigDecimal.ROUND_HALF_UP).subtract(returnReductionAmount);// 因为先减了所以要加回去
									} else {
										newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newOrderDetail.getGiftDeductionTotal()).subtract(returnReductionAmount);
									}
									BigDecimal newDiscountAmount = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newSubtotal);
									newOrderDetail.setSubtotal(newSubtotal);
									newOrderDetail.setReductionAmount(returnReductionAmount);
									newOrderDetail.setDiscountAmount(newDiscountAmount);
									//                                newOrderDetail.setDetailType(2);
									// 原来的也得重算
									// 原来抹零重新计算
									reductionAmount = reductionAmount.subtract(returnReductionAmount);
									salesDetail.setReductionAmount(reductionAmount);

									discountAmount = discountAmount.subtract(newDiscountAmount);
									subtotal = subtotal.subtract(newSubtotal);
									salesDetail.setDiscountAmount(discountAmount);
									salesDetail.setSubtotal(subtotal);
								} else {
									BigDecimal divide = subtotal.add(giftDeductionTotal).divide(BigDecimal.valueOf(sellingNum), 2, BigDecimal.ROUND_HALF_UP);
									// 组合算
									if (needReturnCard > 0) {
										int i1 = returnNum - needReturnCard;
										newSubtotal = divide.multiply(BigDecimal.valueOf(i1));
										BigDecimal multiply = divide.subtract(newOrderDetail.getGiftDeductionTotal()).multiply(BigDecimal.valueOf(needReturnCard));
										newSubtotal = newSubtotal.add(multiply);
									} else {
										// 直接算
										newSubtotal = divide.multiply(BigDecimal.valueOf(returnNum));
									}

									newOrderDetail.setSubtotal(newSubtotal);
									// 原来的也得重算
									subtotal = subtotal.subtract(newSubtotal);
									salesDetail.setSubtotal(subtotal);
								}
								newOrderDetail.setSellingNum(returnNum);
								newOrderDetail.setProductStatus(12);
								newOrderDetail.setBeforeTreatmentNo(salesDetail.getBeforeTreatmentNo());
								newOrderDetail.setAfterTreatmentNo(salesDetail.getAfterTreatmentNo());
								newOrderDetail.setWarehouseName(purchaseProduct.getWarehouseName());
								newOrderDetail.setWarehouseId(purchaseProduct.getWarehouseId());
								newOrderDetail.setBatchNumber(purchaseProduct.getBatchNumber());
								newOrderDetail.setValidity(purchaseProduct.getValidity());
								newOrderDetail.setUnit(purchaseProduct.getUnit());
								newOrderDetail.setCreateTime(currDate);
								salesOrderDetailMapper.insert(newOrderDetail);
								Long salesPurchaseId = purchaseProduct.getSalesPurchaseId();
								if (Objects.nonNull(salesPurchaseId)) {
									SalesPurchase updateSalesPurchase = new SalesPurchase();
									updateSalesPurchase.setId(salesPurchaseId);
									updateSalesPurchase.setDetailId(newOrderDetail.getId());
									forSalesOrderDetails.add(newOrderDetail);
									salesPurchaseMapper.updateSalesPurchase(updateSalesPurchase);
								}

								sellingNum -= returnNum;
								salesDetail.setSellingNum(sellingNum);
								salesOrderDetailMapper.updateById(salesDetail);
							}
						} else {
							// 定制采购无流水
							throw new ServiceException("定制采购无流水");
						}

					} else {
						// 等于这条
                        List<PurchaseProduct> purchaseProducts = getSalesPurchaseProducts(salesOrder.getId(), salesDetail.getId());
                        if (!CollectionUtils.isEmpty(purchaseProducts)) {
							salesDetail.setWarehouseName(purchaseProducts.get(0).getWarehouseName());
							salesDetail.setWarehouseId(purchaseProducts.get(0).getWarehouseId());
							salesDetail.setBatchNumber(purchaseProducts.get(0).getBatchNumber());
							salesDetail.setValidity(purchaseProducts.get(0).getValidity());
							salesDetail.setUnit(purchaseProducts.get(0).getUnit());
							salesOrderDetailMapper.updateById(salesDetail);
						}
						forSalesOrderDetails.add(salesDetail);
					}
				}
			} else {
				forSalesOrderDetails.add(salesDetail);
			}
		}

        // 获取日志所需的患者名称
        StringBuilder memberName = getMeberName(salesOrder.getPatientId());
        // 库存流水日志数据
        List<PurchaseProduct> flowList;
        if (EditTypeEnum.SALE_CANCEL.equals(editType)) {
            flowList = initCancelSalesFlows(forSalesOrderDetails); // 初始化"取消销售"的日志
        } else {
            flowList = initSaleAfterFlows(salesOrder, forSalesOrderDetails, memberName); // 初始化"销售，售后（退换货）"的日志
        }
		// 如果 forSalesOrderDetails 里面有值  但是流水没找到就说明要找了
		if (forSalesOrderDetails.size() > 0 && flowList.size() == 0) {
			throw new ServiceException("销售新增库存流水失败！");
		}
		boolean repertoryFlow = true;
		if (flowList.size() > 0) {
			repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(flowList, editType.getFlowType(), editType.getStorageType());
		}
		return repertoryFlow;
	}

    /**
     * 初始化取消销售日志
     * @param forSalesOrderDetails
     */
    private List<PurchaseProduct> initCancelSalesFlows(List<SalesOrderDetail> forSalesOrderDetails) {
        // 库存流水日志数据
        List<PurchaseProduct> flowList = new ArrayList<>();
        for (SalesOrderDetail salesDetail : forSalesOrderDetails) {
            // 冲红
            RepertoryFlow repertoryFlowParam = new RepertoryFlow();
            // 查采购退货的
            repertoryFlowParam.setStorageType(10);
            repertoryFlowParam.setBusinessId(salesDetail.getId());
            List<PurchaseProduct> repertoryFlows = iRepertoryFlowService.selectListByRepertoryFlow(repertoryFlowParam);
            for (PurchaseProduct purchaseProduct : repertoryFlows) {
                Integer inventoryQuantity = purchaseProduct.getInventoryQuantity();
                Integer availableStock = purchaseProduct.getAvailableStock();
                purchaseProduct.setAvailableStock(availableStock + inventoryQuantity);
                purchaseProductMapper.updateById(purchaseProduct);
            }
            flowList.addAll(repertoryFlows);
        }
        return flowList;
    }

    /**
     * 初始化售后日志
     * @param salesOrder
     * @param forSalesOrderDetails
     * @param memberName
     * @return
     */
    private List<PurchaseProduct> initSaleAfterFlows(SalesOrder salesOrder, List<SalesOrderDetail> forSalesOrderDetails, StringBuilder memberName) {
        // 库存流水日志数据
        List<PurchaseProduct> flowList = new ArrayList<>();

        for (SalesOrderDetail salesDetail : forSalesOrderDetails) {
            // 查询对应销售单的销售采购记录
            List<PurchaseProduct> purchaseProducts = getSalesPurchaseProducts(salesOrder.getId(), salesDetail.getId());

            if (!CollectionUtils.isEmpty(purchaseProducts)) {
                BigDecimal subtotal = salesDetail.getSubtotal();
                BigDecimal dividePrice = subtotal.divide(BigDecimal.valueOf(salesDetail.getSellingNum()), 4,BigDecimal.ROUND_HALF_UP);
                BigDecimal sumPrice = new BigDecimal("0.00");
                for (int i = 0; i < purchaseProducts.size(); i++) {
                    PurchaseProduct purchaseProduct = purchaseProducts.get(i);
                    purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
                    purchaseProduct.setBusinessId(salesDetail.getId());
                    purchaseProduct.setRemark(salesDetail.getRemark());
                    purchaseProduct.setCreateBy(salesOrder.getSalesUserId());
                    purchaseProduct.setDeptId(salesOrder.getDeptId());
                    if (Objects.nonNull(salesDetail.getDeliveryTime())) {
                        purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
                    }
                    purchaseProduct.setMemberId(salesOrder.getPatientId());
                    purchaseProduct.setMemberName(memberName.toString());
                    purchaseProduct.setPrice(salesDetail.getSellingPrice());
                    Integer storageNum = purchaseProduct.getInventoryQuantity();
                    BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(storageNum));
                    purchaseProduct.setSubtotal(multiply);
                    if (i == purchaseProducts.size() - 1) {
                        BigDecimal subtract = subtotal.subtract(sumPrice);
                        purchaseProduct.setSubtotal(subtract);
                        break;
                    }
                    sumPrice = sumPrice.add(multiply);
                }
                flowList.addAll(purchaseProducts);
            } else {
                // 这边是为了解决当时没有占到库存 然后导致生成不了流水的问题
                PurchaseProduct queryProductParam = new PurchaseProduct();
                BeanUtils.copyProperties(salesDetail, queryProductParam);
                List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getSalesNoFlowListByParam(queryProductParam);
                List<PurchaseProduct> purchaseProductsList = iRepertoryFlowService.convertFlowData(
                        purchaseProductList, salesDetail.getSellingNum(),salesOrder.getSalesNo(), salesDetail.getId());
                BigDecimal subtotal = salesDetail.getSubtotal();
                BigDecimal dividePrice = subtotal.divide(BigDecimal.valueOf(salesDetail.getSellingNum()), 4,
                        BigDecimal.ROUND_HALF_UP);
                BigDecimal sumPrice = new BigDecimal("0.00");
                for (int i = 0; i < purchaseProductsList.size(); i++) {
                    PurchaseProduct purchaseProduct = purchaseProductsList.get(i);
                    purchaseProduct.setPrice(salesDetail.getSellingPrice());
                    purchaseProduct.setRemark(salesDetail.getRemark());
                    purchaseProduct.setDeptId(salesOrder.getDeptId());
                    purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
                    purchaseProduct.setBusinessId(salesDetail.getId());
                    purchaseProduct.setMemberId(salesOrder.getPatientId());
                    purchaseProduct.setInventoryQuantity(salesDetail.getSellingNum());
                    purchaseProduct.setMemberName(memberName.toString());
                    if (Objects.nonNull(salesDetail.getDeliveryTime())) {
                        purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
                    }
                    if (i == purchaseProducts.size() - 1) {
                        BigDecimal subtract = subtotal.subtract(sumPrice);
                        purchaseProduct.setSubtotal(subtract);
                        break;
                    }
                    Integer storageNum = purchaseProduct.getInventoryQuantity();
                    BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(storageNum));
                    purchaseProduct.setSubtotal(multiply);
                    sumPrice = sumPrice.add(multiply);
                }
                flowList.addAll(purchaseProductsList);
            }
        }
        return flowList;
    }

    /**
     * 获取患者名称
     * @param patientId
     * @return
     */
    private StringBuilder getMeberName(Long patientId) {
        StringBuilder memberName = new StringBuilder();
        PatientInfo patientInfo = patientInfoMapper.selectById(patientId);
        int year = 0;
        if (Objects.nonNull(patientInfo.getBirthday())) {
            year = DateUtil.ageOfNow(patientInfo.getBirthday());
        }

        if (Objects.nonNull(patientInfo)) {
            String sex = "";
            Integer sexNum = patientInfo.getSex();
            if (sexNum == null || sexNum == 0) {
                sex = "-";
            } else if (sexNum == 1) {
                sex = "男";
            } else if (sexNum == 2) {
                sex = "女";
            }
            memberName.append(patientInfo.getPatientName()).append("/").append(sex).append("/").append(year).append(
                    "岁");
        }
        return memberName;
    }


    private boolean updateStorageFlowOld(SalesOrder salesOrder, List<SalesOrderDetail> salesOrderDetails,
                                         Integer editType) {
		// 因为这边是确认收货 所以先更新采购库存
		//            List<PurchaseProduct> returnProductVoList = returnProductMapper.productListByReturnId(returnInfo
        //            .getId());
		Integer type = 2;
		Integer storageType = 10;
		boolean flag = true;
		if (editType.equals(2)) {
			flag = false;
			type = 1;
			storageType = 12;
		} else if (editType.equals(3)) {
			storageType = 15;
		}
		List<PurchaseProduct> flowDataList = new ArrayList<>();
		PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
		int nowYear = DateUtil.year(new Date());
		int year = 0;
		if (Objects.nonNull(patientInfo.getBirthday())) {

			year = DateUtil.ageOfNow(patientInfo.getBirthday());
		}
		StringBuilder memberName = new StringBuilder();
		if (Objects.nonNull(patientInfo)) {
			String sex = "";
			Integer sexNum = patientInfo.getSex();
			if (sexNum == null || sexNum == 0) {
				sex = "-";
			} else if (sexNum == 1) {
				sex = "男";
			} else if (sexNum == 2) {
				sex = "女";
			}
			memberName.append(patientInfo.getPatientName()).append("/").append(sex).append("/").append(year).append(
			        "岁");
		}
		for (SalesOrderDetail salesDetail : salesOrderDetails) {
			if (salesDetail.getProductPurchaseType().equals(2)) {
				continue;
			}
			if (flag) {
				PurchaseProduct queryProductParam = new PurchaseProduct();
				BeanUtils.copyProperties(salesDetail, queryProductParam);
				List<PurchaseProduct> purchaseProductList =
                        purchaseProductMapper.getSalesNoFlowListByParam(queryProductParam);
				List<PurchaseProduct> purchaseProducts = iRepertoryFlowService.convertFlowData(purchaseProductList,
                        salesDetail.getSellingNum(), salesOrder.getSalesNo(), salesDetail.getId());
				BigDecimal subtotal = salesDetail.getSubtotal();
				BigDecimal dividePrice = subtotal.divide(BigDecimal.valueOf(salesDetail.getSellingNum()), 4,
                        BigDecimal.ROUND_HALF_UP);
				BigDecimal sumPrice = new BigDecimal("0.00");
				for (int i = 0; i < purchaseProducts.size(); i++) {
					PurchaseProduct purchaseProduct = purchaseProducts.get(i);
					purchaseProduct.setPrice(salesDetail.getSellingPrice());
					purchaseProduct.setRemark(salesDetail.getRemark());
					purchaseProduct.setDeptId(salesOrder.getDeptId());
					purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
					purchaseProduct.setBusinessId(salesDetail.getId());
					purchaseProduct.setMemberId(salesOrder.getPatientId());
					purchaseProduct.setMemberName(memberName.toString());
					if (Objects.nonNull(salesDetail.getDeliveryTime())) {
						purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
					}
					if (i == purchaseProducts.size() - 1) {
						BigDecimal subtract = subtotal.subtract(sumPrice);
						purchaseProduct.setSubtotal(subtract);
						break;
					}
					Integer storageNum = purchaseProduct.getInventoryQuantity();
					BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(storageNum));
					purchaseProduct.setSubtotal(multiply);
					sumPrice = sumPrice.add(multiply);
				}
				flowDataList.addAll(purchaseProducts);

			} else {
				// 冲红
				RepertoryFlow repertoryFlowParam = new RepertoryFlow();
				// 查采购退货的
				repertoryFlowParam.setStorageType(10);
				repertoryFlowParam.setBusinessId(salesDetail.getId());
				List<PurchaseProduct> repertoryFlows =
                        iRepertoryFlowService.selectListByRepertoryFlow(repertoryFlowParam);
				for (PurchaseProduct purchaseProduct : repertoryFlows) {
					Integer inventoryQuantity = purchaseProduct.getInventoryQuantity();
					Integer availableStock = purchaseProduct.getAvailableStock();
					purchaseProduct.setAvailableStock(availableStock + inventoryQuantity);
					purchaseProductMapper.updateById(purchaseProduct);
				}
				flowDataList.addAll(repertoryFlows);
			}
		}
		if (flowDataList.size() == 0) {
			throw new ServiceException("销售无流水新增库存流水失败！");
		}
		boolean repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(flowDataList, type, storageType);
		return repertoryFlow;
	}


	private boolean updateStorageFlowSalesPurchase(SalesOrder salesOrder, List<SalesOrderDetail> salesOrderDetails,
                                                   Integer editType) {
		// 因为这边是确认收货 所以先更新采购库存
		Date currDate = new Date();
		BigDecimal discount = salesOrder.getDiscount();
		List<SalesOrderDetail> forSalesOrderDetails = new ArrayList<>();
		for (SalesOrderDetail salesDetail : salesOrderDetails) {
			if (salesDetail.getProductPurchaseType().equals(2)) {
				// 如果是 定制采购流水
				// 定制采购交付需要拆分销售明细单方便后面好
				Integer sellingNum = salesDetail.getSellingNum();
				if (sellingNum > 1) {
                    List<PurchaseProduct> purchaseProducts = getSalesPurchaseProducts(salesOrder.getId(), salesDetail.getId());
                    if (!CollectionUtils.isEmpty(purchaseProducts)) {
						// 重新计算 优惠金额 和 小计
						BigDecimal discountAmount = salesDetail.getDiscountAmount();
						BigDecimal subtotal = salesDetail.getSubtotal();
						BigDecimal giftDeductionTotal = salesDetail.getGiftDeductionTotal();
						BigDecimal reductionAmount = salesDetail.getReductionAmount();

						String useReceiveGift = salesDetail.getUseReceiveGift();
						BigDecimal sellingPrice = salesDetail.getSellingPrice();

						for (PurchaseProduct purchaseProduct : purchaseProducts) {
							SalesOrderDetail newOrderDetail = new SalesOrderDetail();
							BeanUtils.copyProperties(salesDetail, newOrderDetail);
							Integer returnNum = purchaseProduct.getInventoryQuantity();
							if (returnNum == sellingNum) {
								salesDetail.setWarehouseName(purchaseProduct.getWarehouseName());
								salesDetail.setWarehouseId(purchaseProduct.getWarehouseId());
								salesDetail.setBatchNumber(purchaseProduct.getBatchNumber());
								salesDetail.setValidity(purchaseProduct.getValidity());
								salesDetail.setUnit(purchaseProduct.getUnit());
								salesDetail.setSellingNum(returnNum);
								forSalesOrderDetails.add(salesDetail);
								salesOrderDetailMapper.updateById(salesDetail);
								break;
							}
							int needReturnCard = 0;
							if (StringUtils.isNotEmpty(useReceiveGift)) {
								// 使用了优惠卡
								String[] split = useReceiveGift.split(",");
								List<String> stringList = Stream.of(split).collect(Collectors.toList());
								int length = split.length;
								// 用了几张优惠卡
								int num = sellingNum - returnNum;
								int cardUseNum = length - num; // 要退的卡数
								needReturnCard = cardUseNum;
								List<String> returnGiftList = new ArrayList<>();
								if (cardUseNum > 0) {
									BigDecimal giftDeductionTotalDivide =
                                            giftDeductionTotal.divide(BigDecimal.valueOf(length), 4,
                                                    BigDecimal.ROUND_HALF_UP);
									BigDecimal returnGiftDeductionTotal =
                                            giftDeductionTotalDivide.multiply(BigDecimal.valueOf(cardUseNum));
									newOrderDetail.setGiftDeductionTotal(returnGiftDeductionTotal);
									giftDeductionTotal = giftDeductionTotal.subtract(returnGiftDeductionTotal);
									salesDetail.setGiftDeductionTotal(giftDeductionTotal);
									// 需要退会员卡了
									for (int j = 0; j < cardUseNum; j++) {
										returnGiftList.add(split[j]);
									}
									newOrderDetail.setUseReceiveGift(StringUtils.join(returnGiftList, ","));
								} else {
									newOrderDetail.setUseReceiveGift(null);
									newOrderDetail.setGiftDeductionTotal(new BigDecimal(0.00));
								}
								// 更改原来商品明细的使用会员卡号
								stringList.removeAll(returnGiftList);
								useReceiveGift = StringUtils.join(stringList, ",");
								salesDetail.setUseReceiveGift(useReceiveGift);

							}
							BigDecimal returnReductionAmount = reductionAmount.divide(BigDecimal.valueOf(sellingNum),
                                    2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(returnNum));
							BigDecimal newSubtotal = new BigDecimal("0.00");// 重新算
							if (!salesDetail.getDetailType().equals(1)) {
								if (discount != null && discount.doubleValue() > 0) {

									newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newOrderDetail.getGiftDeductionTotal()).multiply(discount).divide(new BigDecimal("10"), 4, BigDecimal.ROUND_HALF_UP).subtract(returnReductionAmount);// 因为先减了所以要加回去
								} else {
									newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newOrderDetail.getGiftDeductionTotal()).subtract(returnReductionAmount);
								}
								BigDecimal newDiscountAmount = sellingPrice.multiply(BigDecimal.valueOf(returnNum)).subtract(newSubtotal);
								newOrderDetail.setSubtotal(newSubtotal);
								newOrderDetail.setReductionAmount(returnReductionAmount);
								newOrderDetail.setDiscountAmount(newDiscountAmount);
								//                                newOrderDetail.setDetailType(2);
								// 原来的也得重算
								// 原来抹零重新计算
								reductionAmount = reductionAmount.subtract(returnReductionAmount);
								salesDetail.setReductionAmount(reductionAmount);

								discountAmount = discountAmount.subtract(newDiscountAmount);
								subtotal = subtotal.subtract(newSubtotal);
								salesDetail.setDiscountAmount(discountAmount);
								salesDetail.setSubtotal(subtotal);
							} else {
								BigDecimal divide = subtotal.add(giftDeductionTotal).divide(BigDecimal.valueOf(sellingNum), 2, BigDecimal.ROUND_HALF_UP);
								// 组合算
								if (needReturnCard > 0) {
									int i1 = returnNum - needReturnCard;
									newSubtotal = divide.multiply(BigDecimal.valueOf(i1));
									BigDecimal multiply = divide.subtract(newOrderDetail.getGiftDeductionTotal()).multiply(BigDecimal.valueOf(needReturnCard));
									newSubtotal = newSubtotal.add(multiply);
								} else {
									// 直接算
									newSubtotal = divide.multiply(BigDecimal.valueOf(returnNum));
								}

								newOrderDetail.setSubtotal(newSubtotal);
								// 原来的也得重算
								subtotal = subtotal.subtract(newSubtotal);
								salesDetail.setSubtotal(subtotal);
							}
							newOrderDetail.setSellingNum(returnNum);
							newOrderDetail.setProductStatus(12);
							newOrderDetail.setBeforeTreatmentNo(salesDetail.getBeforeTreatmentNo());
							newOrderDetail.setAfterTreatmentNo(salesDetail.getAfterTreatmentNo());
							newOrderDetail.setWarehouseName(purchaseProduct.getWarehouseName());
							newOrderDetail.setWarehouseId(purchaseProduct.getWarehouseId());
							newOrderDetail.setBatchNumber(purchaseProduct.getBatchNumber());
							newOrderDetail.setValidity(purchaseProduct.getValidity());
							newOrderDetail.setUnit(purchaseProduct.getUnit());
							newOrderDetail.setCreateTime(currDate);
							salesOrderDetailMapper.insert(newOrderDetail);
							Long salesPurchaseId = purchaseProduct.getSalesPurchaseId();
							if (Objects.nonNull(salesPurchaseId)) {
								SalesPurchase updateSalesPurchase = new SalesPurchase();
								updateSalesPurchase.setId(salesPurchaseId);
								updateSalesPurchase.setDetailId(newOrderDetail.getId());
								forSalesOrderDetails.add(newOrderDetail);
								salesPurchaseMapper.updateSalesPurchase(updateSalesPurchase);
							}

							sellingNum -= returnNum;
							salesDetail.setSellingNum(sellingNum);
							salesOrderDetailMapper.updateById(salesDetail);
						}
					} else {
						// 定制采购无流水
						throw new ServiceException("定制采购无流水");
					}

				} else {
					forSalesOrderDetails.add(salesDetail);
				}

			} else {
				forSalesOrderDetails.add(salesDetail);
			}
		}

		//            List<PurchaseProduct> returnProductVoList = returnProductMapper.productListByReturnId(returnInfo
        //            .getId());
		Integer type = 2;
		Integer storageType = 10;
		boolean flag = true;
		if (editType.equals(2)) {
			flag = false;
			type = 1;
			storageType = 12;
		} else if (editType.equals(3)) {
			storageType = 15;
		}
		List<PurchaseProduct> flowDataList = new ArrayList<>();
		PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
		int nowYear = DateUtil.year(new Date());
		int year = 0;
		if (Objects.nonNull(patientInfo.getBirthday())) {

			year = DateUtil.ageOfNow(patientInfo.getBirthday());
		}
		StringBuilder memberName = new StringBuilder();
		if (Objects.nonNull(patientInfo)) {
			String sex = "";
			Integer sexNum = patientInfo.getSex();
			if (sexNum == null || sexNum == 0) {
				sex = "-";
			} else if (sexNum == 1) {
				sex = "男";
			} else if (sexNum == 2) {
				sex = "女";
			}
			memberName.append(patientInfo.getPatientName()).append("/").append(sex).append("/").append(year).append(
			        "岁");
		}
		for (SalesOrderDetail salesDetail : forSalesOrderDetails) {

			BigDecimal orderDetailSubtotal = salesDetail.getSubtotal();
			Integer orderDetailSellingNum = salesDetail.getSellingNum();

			if (flag) {
                final Long id = salesOrder.getId();
                final Long detailId = salesDetail.getId();
                List<PurchaseProduct> purchaseProducts = getSalesPurchaseProducts(id, detailId);

                if (!CollectionUtils.isEmpty(purchaseProducts)) {
					BigDecimal subtotal = orderDetailSubtotal;
					BigDecimal dividePrice = subtotal.divide(BigDecimal.valueOf(orderDetailSellingNum), 4,
                            BigDecimal.ROUND_HALF_UP);
					BigDecimal sumPrice = new BigDecimal("0.00");


					for (int i = 0; i < purchaseProducts.size(); i++) {
						PurchaseProduct purchaseProduct = purchaseProducts.get(i);
						purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
						purchaseProduct.setBusinessId(salesDetail.getId());
						purchaseProduct.setRemark(salesDetail.getRemark());
						purchaseProduct.setCreateBy(salesOrder.getSalesUserId());
						purchaseProduct.setDeptId(salesOrder.getDeptId());
						if (Objects.nonNull(salesDetail.getDeliveryTime())) {
							purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
						}
						purchaseProduct.setMemberId(salesOrder.getPatientId());
						purchaseProduct.setMemberName(memberName.toString());
						purchaseProduct.setPrice(salesDetail.getSellingPrice());
						Integer storageNum = purchaseProduct.getInventoryQuantity();
						BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(storageNum));
						purchaseProduct.setSubtotal(multiply);
						if (i == purchaseProducts.size() - 1) {
							BigDecimal subtract = subtotal.subtract(sumPrice);
							purchaseProduct.setSubtotal(subtract);
							break;
						}
						sumPrice = sumPrice.add(multiply);
					}
					flowDataList.addAll(purchaseProducts);
				} else {
					// 这边是为了解决当时没有占到库存 然后导致生成不了流水的问题
					PurchaseProduct queryProductParam = new PurchaseProduct();
					BeanUtils.copyProperties(salesDetail, queryProductParam);
					List<PurchaseProduct> purchaseProductList =
                            purchaseProductMapper.getSalesNoFlowListByParam(queryProductParam);
					List<PurchaseProduct> purchaseProductsList =
                            iRepertoryFlowService.convertFlowData(purchaseProductList, salesDetail.getSellingNum(),
                                    salesOrder.getSalesNo(), salesDetail.getId());
					BigDecimal subtotal = salesDetail.getSubtotal();
					BigDecimal dividePrice = subtotal.divide(BigDecimal.valueOf(salesDetail.getSellingNum()), 4,
                            BigDecimal.ROUND_HALF_UP);
					BigDecimal sumPrice = new BigDecimal("0.00");
					for (int i = 0; i < purchaseProductsList.size(); i++) {
						PurchaseProduct purchaseProduct = purchaseProductsList.get(i);
						purchaseProduct.setPrice(salesDetail.getSellingPrice());
						purchaseProduct.setRemark(salesDetail.getRemark());
						purchaseProduct.setDeptId(salesOrder.getDeptId());
						purchaseProduct.setPurchaseNumber(salesOrder.getSalesNo());
						purchaseProduct.setBusinessId(salesDetail.getId());
						purchaseProduct.setMemberId(salesOrder.getPatientId());
						purchaseProduct.setInventoryQuantity(salesDetail.getSellingNum());
						purchaseProduct.setMemberName(memberName.toString());
						if (Objects.nonNull(salesDetail.getDeliveryTime())) {
							purchaseProduct.setCreateTime(salesDetail.getDeliveryTime());
						}
						if (i == purchaseProducts.size() - 1) {
							BigDecimal subtract = subtotal.subtract(sumPrice);
							purchaseProduct.setSubtotal(subtract);
							break;
						}
						Integer storageNum = purchaseProduct.getInventoryQuantity();
						BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(storageNum));
						purchaseProduct.setSubtotal(multiply);
						sumPrice = sumPrice.add(multiply);
					}
					flowDataList.addAll(purchaseProductsList);
				}
				//                    }
			} else {
				// 冲红
				RepertoryFlow repertoryFlowParam = new RepertoryFlow();
				// 查采购退货的
				repertoryFlowParam.setStorageType(10);
				repertoryFlowParam.setBusinessId(salesDetail.getId());
				List<PurchaseProduct> repertoryFlows =
                        iRepertoryFlowService.selectListByRepertoryFlow(repertoryFlowParam);
				for (PurchaseProduct purchaseProduct : repertoryFlows) {
					Integer inventoryQuantity = purchaseProduct.getInventoryQuantity();
					Integer availableStock = purchaseProduct.getAvailableStock();
					purchaseProduct.setAvailableStock(availableStock + inventoryQuantity);
					purchaseProductMapper.updateById(purchaseProduct);
				}
				flowDataList.addAll(repertoryFlows);
			}
		}
		// 如果 forSalesOrderDetails 里面有值  但是流水没找到就说明要找了
		if (forSalesOrderDetails.size() > 0 && flowDataList.size() == 0) {
			throw new ServiceException("销售新增库存流水失败！");
		}
		boolean repertoryFlow = true;
		if (flowDataList.size() > 0) {
			repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(flowDataList, type, storageType);
		}
		return repertoryFlow;
	}

    private List<PurchaseProduct> getSalesPurchaseProducts(Long id, Long detailId) {
        SalesPurchase salesPurchase = new SalesPurchase();
        salesPurchase.setSalesId(id);
        salesPurchase.setDetailId(detailId);
        return salesPurchaseMapper.selectPurchaseList(salesPurchase);
    }


    @Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult cancel(SalesOrder salesOrder) {
		SalesOrder salesOrderInfo = baseMapper.selectById(salesOrder.getId());
		salesOrderInfo.setOrderStatus(7);
		baseMapper.updateById(salesOrderInfo);
		// 更新库存
		List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectListBySales(salesOrder);
		for (SalesOrderDetail detail : salesOrderDetails) {
			if (StringUtils.isNotEmpty(detail.getUseReceiveGift())) {
				List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(detail.getUseReceiveGift());
				for (GiftReceive receive : giftReceives) {
					receive.setStatus(0);
					receive.setRelatedRechargeNo(null);
					receive.setWrittenOffUserId(null);
					receive.setWrittenOffDeptId(null);
					giftReceiveMapper.updateByGiftReceiveId(receive);
				}
			}
			detail.setProductStatus(19);
			salesOrderDetailMapper.updateById(detail);
		}
		boolean b = occupyPurchaseProduct(salesOrder, salesOrderDetails, 2);
		if (false == b) {
			throw new ServiceException("取消失败！原因：增加销售单采购商品库存流水失败。");
		}
		return AjaxResult.success("操作成功！");
	}

	/**
	 * 修改销售单信息
	 *
	 * @param salesOrder 销售单信息
	 * @return 结果
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int updateSalesOrder(SalesOrder salesOrder) {
		salesOrder.setUpdateTime(DateUtils.getNowDate());
		SalesOrder salesOrderInfo = salesOrderMapper.selectById(salesOrder.getId());
		Date date = new Date();
		if (Objects.nonNull(salesOrder.getOrderStatus()) && salesOrder.getOrderStatus().equals(4)) {
			if (Objects.nonNull(salesOrder.getOrderDetailId())) {
				// 指定商品（detailId）交付
				SalesOrderDetail detail = salesOrderDetailMapper.selectById(salesOrder.getOrderDetailId());
				SysDept sysDept = sysDeptService.selectDeptById(SecurityUtils.getDeptId());
				// 更新销售单商品
				detail.setProductStatus(12);
				detail.setDeliveryDeptId(sysDept.getDeptId());
				detail.setDeliveryDeptName(sysDept.getDeptName());
				detail.setDeliveryTime(date);
				salesOrderDetailMapper.updateById(detail);
				// 更新销售单原始商品明细
				SalesOriginalOrderDetail originalOrderDetail =
                        originalOrderDetailMapper.selectByDetailId(detail.getId());
				if (Objects.nonNull(originalOrderDetail)) {
					originalOrderDetail.setDeliveryDeptId(sysDept.getDeptId());
					originalOrderDetail.setDeliveryDeptName(sysDept.getDeptName());
					originalOrderDetail.setDeliveryTime(date);
					originalOrderDetail.setProductStatus(12);
					originalOrderDetailMapper.updateById(originalOrderDetail);
				}
				// 更新采购库存调整
				String useReceiveGift = detail.getUseReceiveGift();
				if (StringUtils.isNotEmpty(useReceiveGift)) {
					List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
					for (GiftReceive receive : giftReceives) {
						receive.setStatus(1);
						giftReceiveMapper.updateById(receive);
					}
				}

				List<SalesOrderDetail> salesOrderDetails = new ArrayList<>();
				salesOrderDetails.add(detail);
				if (detail.getDetailType().equals(1)) {
					// 换货的时候得是 15
					insertFlowBySalesUpdate(salesOrderInfo, salesOrderDetails, EditTypeEnum.SALE_AFTER);
				} else {
					insertFlowBySalesUpdate(salesOrderInfo, salesOrderDetails, EditTypeEnum.SALE);
				}
			} else {
				// 整（销售）单交付
				List<SalesOrderDetail> salesOrderDetails = salesOrderDetailMapper.selectBySalesId(salesOrder.getId());
				// 过滤数据，查出未交付的销售单商品
				List<SalesOrderDetail> collect =
                        salesOrderDetails.stream().filter(o -> o.getProductStatus().equals(11)).collect(Collectors.toList());
				if (!CollectionUtils.isEmpty(collect)) {
					SysDept sysDept = sysDeptService.selectDeptById(SecurityUtils.getDeptId());
					for (SalesOrderDetail detail : collect) {
						// 更新销售单商品明细
						detail.setProductStatus(12);
						detail.setDeliveryDeptId(sysDept.getDeptId());
						detail.setDeliveryDeptName(sysDept.getDeptName());
						detail.setDeliveryTime(date);
						salesOrderDetailMapper.updateById(detail);
						// 更新销售单原始商品明细
						SalesOriginalOrderDetail originalOrderDetail =
                                originalOrderDetailMapper.selectByDetailId(detail.getId());
						if (Objects.nonNull(originalOrderDetail)) {
							originalOrderDetail.setDeliveryDeptId(sysDept.getDeptId());
							originalOrderDetail.setDeliveryDeptName(sysDept.getDeptName());
							originalOrderDetail.setDeliveryTime(date);
							originalOrderDetail.setProductStatus(12);
							originalOrderDetailMapper.updateById(originalOrderDetail);
						}
						// 更新采购库存调整
						String useReceiveGift = detail.getUseReceiveGift();
						if (StringUtils.isNotEmpty(useReceiveGift)) {
							List<GiftReceive> giftReceives = giftReceiveMapper.selectIdList(useReceiveGift);
							for (GiftReceive receive : giftReceives) {
								receive.setStatus(1);
								giftReceiveMapper.updateById(receive);
							}
						}
					}

					List<SalesOrderDetail> exchangeDetailList =
                            collect.stream().filter(o -> o.getDetailType() == 1).collect(Collectors.toList());
					if (!CollectionUtils.isEmpty(exchangeDetailList)) {
						insertFlowBySalesUpdate(salesOrderInfo, exchangeDetailList, EditTypeEnum.SALE_AFTER);
						collect.removeAll(exchangeDetailList);
						insertFlowBySalesUpdate(salesOrderInfo, collect, EditTypeEnum.SALE);
					} else {
						insertFlowBySalesUpdate(salesOrderInfo, collect, EditTypeEnum.SALE);
					}
				}
			}
			List<Integer> collectProdStatus = salesOrderDetailMapper.selectBySalesId(salesOrder.getId()).stream()
					.map(SalesOrderDetail::getProductStatus).distinct().collect(Collectors.toList());
			Integer orderStatus = ProcessOrderUtil.processOrderStatusByStatus(collectProdStatus);
			salesOrder.setOrderStatus(orderStatus);
		}
		return salesOrderMapper.updateSalesOrder(salesOrder);
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult importNoFlowExcel(List<SalesNoFlowVo> list) {
		for (SalesNoFlowVo salesNoFlowVo : list) {
			String salesNo = salesNoFlowVo.getSalesNo();
			Long id = salesNoFlowVo.getId();
			SalesOrderDetail salesOrderDetail = salesOrderDetailMapper.selectSalesOrderDetailById(id);
			SalesOrder salesOrder = salesOrderMapper.selectById(salesOrderDetail.getSalesId());
			List<SalesOrderDetail> detailList = new ArrayList<>();
			detailList.add(salesOrderDetail);
			updateStorageFlowOld(salesOrder, detailList, 1);
		}
		return AjaxResult.success();
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult importSalesPurchaseNoFlowExcel(List<SalesPurchaseNoFlowVo> list) {
		for (SalesPurchaseNoFlowVo salesNoFlowVo : list) {
			String salesNo = salesNoFlowVo.getSalesNo();
			Long id = salesNoFlowVo.getId();
			SalesOrderDetail salesOrderDetail = salesOrderDetailMapper.selectSalesOrderDetailById(id);
			SalesOrder salesOrder = salesOrderMapper.selectById(salesOrderDetail.getSalesId());
			List<SalesOrderDetail> detailList = new ArrayList<>();
			detailList.add(salesOrderDetail);
			updateStorageFlowSalesPurchase(salesOrder, detailList, 1);
		}
		return AjaxResult.success();
	}


	@Transactional(rollbackFor = Exception.class)
	@Override
	public AjaxResult importUnUseExcel(List<SalesNoFlowVo> list) {
		for (SalesNoFlowVo salesNoFlowVo : list) {
			String salesNo = salesNoFlowVo.getSalesNo();
			Long id = salesNoFlowVo.getId();
			SalesOrderDetail salesOrderDetail = salesOrderDetailMapper.selectSalesOrderDetailById(id);
			SalesOrder salesOrder = salesOrderMapper.selectById(salesOrderDetail.getSalesId());

			PurchaseProduct queryProductParam = new PurchaseProduct();
			BeanUtils.copyProperties(salesOrderDetail, queryProductParam);
			List<PurchaseProduct> purchaseProductList =
                    purchaseProductMapper.getSalesNoFlowListByParam(queryProductParam);
			List<PurchaseProduct> purchaseProducts = iRepertoryFlowService.convertFlowData(purchaseProductList,
                    salesOrderDetail.getSellingNum(), salesOrder.getSalesNo(), salesOrderDetail.getId());
			// setInventoryQuantity
			for (PurchaseProduct purchaseProduct : purchaseProducts) {
				SalesPurchase salesPurchase = new SalesPurchase();
				salesPurchase.setSalesId(salesOrder.getId());
				salesPurchase.setDetailId(salesOrderDetail.getId());
				salesPurchase.setPurchaseProductId(purchaseProduct.getId());
				salesPurchase.setPurchaseProductNum(purchaseProduct.getInventoryQuantity());
				salesPurchaseMapper.insert(salesPurchase);
			}
		}
		return AjaxResult.success();
	}

	/**
	 * 批量删除销售单信息
	 *
	 * @param ids 需要删除的销售单信息主键
	 * @return 结果
	 */
	@Override
	public int deleteSalesOrderByIds(Long[] ids) {
		return salesOrderMapper.deleteSalesOrderByIds(ids);
	}

	/**
	 * 删除销售单信息信息
	 *
	 * @param id 销售单信息主键
	 * @return 结果
	 */
	@Override
	public int deleteSalesOrderById(Long id) {
		return salesOrderMapper.deleteSalesOrderById(id);
	}
}
